Skip to content

check -p --references misses CE1406 for a database retrieve or a create of a Hidden entity of a Protected module #1652

Open

Description

@kris-bom

Description

Follow-up on #1498 (closed). Since that fix, check -p --references reports CE1406 for a call of a Hidden microflow, a parameter of a Hidden entity, and a Hidden attribute or association used through a typed variable. But the entity of a retrieve from the database or of a create is never checked: a flow outside the Protected module that retrieves or creates a Hidden entity passes check and exec, and mxbuild then refuses it with CE1406.

(The related gap for a Hidden attribute on a call microflow result has its own issue, #1654.)

Steps to reproduce

  1. Create a module AddOn and switch it to export level Protected (module type Add-on) in the module settings:

    mdl 1;
    create module AddOn;
    create persistent entity AddOn.Request (Code: String(50), Secret: String(50));
    create persistent entity AddOn.Internal (Note: String(50));
    alter entity AddOn.Request set export level api;
    alter entity AddOn.Request modify attribute Code: String(50) export level api;

    AddOn.Internal is Hidden, AddOn.Request.Secret is Hidden. show modules shows AddOn | Protected AddOn.

  2. Run cases.mdl against it (ordinary module):

    mdl 1;
    -- Control: a Hidden attribute on a parameter of a Usable entity. Reported today.
    create microflow MyFirstModule.Case0_Control ($Request: AddOn.Request)
      returns String as $Secret
    begin
      declare $Secret String = $Request/Secret;
      return $Secret;
    end;
    
    -- 1: database retrieve of a Hidden entity.
    create microflow MyFirstModule.Case1_RetrieveHidden ()
      returns Boolean as $Found
    begin
      retrieve $Internals from AddOn.Internal;
      $Count = count($Internals);
      declare $Found Boolean = $Count > 0;
      return $Found;
    end;
    
    -- 2: a bare create of a Hidden entity.
    create microflow MyFirstModule.Case2_CreateHidden ()
      returns Boolean as $Created
    begin
      $Internal = create AddOn.Internal;
      declare $Created Boolean = $Internal != empty;
      return $Created;
    end;
  3. mxcli check cases.mdl -p App.mpr --references, then (without the control) mxcli exec and mx check App.mpr.

Expected behavior

check -p --references reports CE1406 for Case1 and Case2, like it does for the control, so exec refuses the script before it writes something the build rejects.

Actual behavior

Only the control is reported:

$ mxcli check cases.mdl -p App.mpr --references
  statement 1: CE1406: declare $Secret is not allowed to use attribute 'AddOn.Request.Secret' because app modules
  cannot reference hidden elements in add-on modules — ...
✗ 1 reference error(s) found

Without the control: ✓ All references valid, exec writes both microflows, and then:

$ mx check App.mpr
[error] [CE1406] "Retrieve object(s) activity 'Retrieve list of Internal from database' is not allowed to use entity 'AddOn.Internal' because app modules cannot reference hidden elements in add-on modules."
[error] [CE1406] "Create object activity 'Create Internal' is not allowed to use entity 'AddOn.Internal' because app modules cannot reference hidden elements in add-on modules."

Environment

  • mxcli v0.28.0 (2026-10-23), macOS arm64
  • mx check: Mendix 11.12.4 (fresh app)
  • check also reproduced on the repository's testdata/testapp (Mendix 11.14.0, clean HOME; check only, no mxbuild 11.14 here)
  • The relevant source on main is unchanged since 2026-10-21, so Nightly 2026-10-25 behaves the same

Root cause

checkFlow (mdl/executor/validate_protected_module_refs.go) calls entityRef only for parameter and return types; the body walk (flowRefCollector) collects pages and microflows. checkFlowMembers (validate_protected_module_members.go) checks the members of a CreateObjectStmt and of a RetrieveStmt's XPath, but not s.EntityType / s.Source. A bare create or a retrieve without a where therefore reaches no check at all.

Proposed fix

In the walkTypedFlow visitor of checkFlowMembers (which already runs only for flows outside the Protected module), check the entity of a create and of a database retrieve:

case *ast.CreateObjectStmt:
    out = appendNonEmpty(out, r.entityRef("create object activity '"+s.Variable+"'", s.EntityType, "app modules"))
    // ... existing member checks
case *ast.RetrieveStmt:
    if s.StartVariable == "" {
        out = appendNonEmpty(out, r.entityRef("retrieve $"+s.Variable, s.Source, "app modules"))
    }
    // ... existing member checks

entityRef already resolves the stated / stored / script-created level and is silent for a Usable entity, an ordinary module and an entity it cannot find.

Tests in TestValidateProtectedModuleRefs (the fixture already has a Hidden MyAddOn.Request and a Usable MyAddOn.Pub):

{"retrieve of hidden entity",
    "create microflow MyFirstModule.R () begin retrieve $l from MyAddOn.Request; end;",
    []string{"CE1406", "entity 'MyAddOn.Request'"}},
{"retrieve of usable entity", "create microflow MyFirstModule.R () begin retrieve $l from MyAddOn.Pub; end;", nil},
{"bare create of hidden entity",
    "create microflow MyFirstModule.C () begin $r = create MyAddOn.Request; end;",
    []string{"CE1406", "entity 'MyAddOn.Request'"}},

and the same in an ordinary module (Open) as the control that stays clean.

I have a fix with tests ready and will open a PR referencing this issue shortly.

Activity

  1. changed the title [-]`check -p --references` misses three CE1406 shapes into a Protected module: a database retrieve, a create object, and a Hidden member of a call result[/-] [+]`check -p --references` misses CE1406 for a database retrieve or a create of a Hidden entity of a Protected module[/+] on Oct 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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