-
Notifications
You must be signed in to change notification settings - Fork 64
Description
Describe the Bug
In Directus 11.x (tested on 11.1.1, containerized/Fly.io), when a Role is linked to a Policy via the directus_access table, the Directus API and Permission Engine incorrectly use the id (primary key) of the directus_access record as the Policy UUID, ignoring the actual policy foreign key column.
This causes "Ghost Policies" where the API reports the Role is linked to a non-existent Policy UUID (which is actually the Access record's UUID), resulting in 403 Forbidden errors even when the database link is correct.
To Reproduce
Create a Role (e.g., "Test Role").
Create a Policy (e.g., "Test Policy") with some permissions.
Link them via SQL (simulating what the UI does, or a migration):
INSERT INTO directus_access (id, role, policy, sort)
VALUES (
gen_random_uuid(), -- Generates a random UUID, e.g., '5fd3eefd...'
'',
'', -- The actual policy, e.g., 'a1111111...'
1
);
Restart Directus (to flush cache).
Query the Role via API: GET /roles/
Observe: The policies array contains '5fd3eefd...' (the Access ID), NOT 'a1111111...' (the Policy ID).
Result: Permissions defined in "Test Policy" are not applied.
Expected Behavior
Directus should read the policy column from directus_access to determine which Policy is linked to the Role. The id of the access record should be irrelevant to the permission logic.
Root Cause Analysis
It appears the internal logic for hydrating Role policies maps the id field of the junction table object to the policy ID, instead of mapping the policy field.
Workaround
Force the directus_access.id to be identical to the directus_access.policy UUID.
INSERT INTO directus_access (id, role, policy, sort)
VALUES (
'', -- ID MUST MATCH POLICY ID
'',
'',
1
);
When id === policy, the bug is masked because reading the wrong column still yields the correct UUID.
Environment
Directus Version: 11.x
Deployment: Docker / Fly.io
Directus Version
11.12.0
Hosting Strategy
Self-Hosted (Docker Image)
Database
PostgreSQL (Neon)