You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: modules/ROOT/pages/authentication-authorization/limitations.adoc
+68-3Lines changed: 68 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -16,10 +16,10 @@ CREATE ROLE unrestricted;
16
16
17
17
Using Neo4j's role-based access control imposes some limitations and implications that users should be aware of, such as:
18
18
19
-
* Impact on query results regardless of whether the indexes are used.
20
-
* Impact results when nodes have multiple labels.
21
-
* Potential performance impacts when querying large graphs with complex security rules.
19
+
* Impact on query results regardless of whether indexes are used.
20
+
* Impact on query results when nodes have multiple labels.
22
21
* The need for careful management of user roles and privileges to avoid unintended data exposure.
22
+
* Potential performance impacts when querying large graphs with complex security rules.
23
23
24
24
[[access-control-limitations-indexes]]
25
25
== Security and indexes
@@ -186,6 +186,71 @@ Otherwise, it will process as described before.
186
186
187
187
In this case, the query will return zero results rather than simply returning the results `Andy` and `Sandy`, which might have been expected.
188
188
189
+
=== Avoiding fail-open `DENY` behavior
190
+
191
+
A `DENY` rule fails open when its criteria is not met, so Neo4j does not apply the restriction and it grants access by default if a broader `GRANT` exists.
192
+
This can lead to unintended data exposure if the `DENY` rule is not carefully crafted.
193
+
194
+
For example, consider the following scenarios:
195
+
196
+
.Example of an un-met `DENY` failing open with property-based RBAC
197
+
====
198
+
You grant a user access to a property, but then try to restrict it with a `DENY` rule that does not match the data.
199
+
If the `DENY` rule does not match any data, it does not apply, and the user can still access the property.
200
+
201
+
[source, cypher]
202
+
----
203
+
GRANT READ {salary} ON GRAPH * NODES Employee TO myRole
204
+
DENY READ {salary} ON GRAPH * FOR (e:Employee) WHERE e.position = 'CEO' TO myRole
205
+
----
206
+
In this case, if the `e.position` property is null or misspelled, the `DENY` rule will not apply, and `myRole` will see the `salary` property.
207
+
208
+
A better way is to use a `GRANT` rule that only allows access to the `salary` property for employees whose position is not 'CEO'.
209
+
[source, cypher]
210
+
----
211
+
GRANT READ {salary} ON GRAPH * FOR (e:Employee) WHERE e.position <> 'CEO' TO myRole
212
+
----
213
+
214
+
Or, if for some reason using `DENY` is unavoidable, the problem can be mitigated by adding an additional `DENY` to cover the case where `e.position` is null:
215
+
[source, cypher]
216
+
----
217
+
DENY READ {salary} ON GRAPH * FOR (e:Employee) WHERE e.position IS NULL TO myRole
218
+
----
219
+
This way, if `e.position` is null, the user will not see the `salary` property, and the `DENY` will not apply.
220
+
221
+
Alternatively, you can add a constraint to ensure that the `e.position` property cannot be null, so the `DENY` condition is always checkable:
222
+
[source, cypher]
223
+
----
224
+
CREATE CONSTRAINT ON (e:Employee) ASSERT e.position IS NOT NULL;
225
+
----
226
+
This way, the `DENY` will never apply due to null values, and the user will not see the `salary` property for employees whose position is 'CEO'.
227
+
228
+
====
229
+
230
+
.Example of an un-met `DENY` failing open with label-based RBAC
231
+
====
232
+
233
+
In a similar way, a `DENY` rule will not apply when it is too broad and does not match the data.
234
+
[source, cypher]
235
+
----
236
+
GRANT READ {salary} ON GRAPH * NODES * TO myRole;
237
+
----
238
+
239
+
This grants read access to the `salary` property on all nodes, including those that should not be accessible.
240
+
241
+
Then, you try to restrict it with a `DENY` rule to prevent access to the `salary` property on nodes labeled `Management`:
242
+
[source, cypher]
243
+
----
244
+
DENY READ {salary} ON GRAPH * NODES Management TO myRole;
245
+
----
246
+
In this case, if the `Management` label is not present on a node that has the `salary` property, the `DENY` rule will not apply, and `myRole` will still see the `salary` property on that node.
247
+
A better way is to use a `GRANT` rule to only allow access to the `salary` property for nodes that have a specific label, such as `IndividualContributor`:
248
+
[source, cypher]
249
+
----
250
+
GRANT READ {salary} ON GRAPH * NODES IndividualContributor TO myRole;
251
+
----
252
+
This way, the user will only see the `salary` property on nodes that have the `IndividualContributor` label, and not on any other nodes.
0 commit comments