Neo4j RBAC and Procedure Whitelisting: An Architecture Note for Least-Privilege Graph Access
Neo4j Enterprise RBAC and procedure whitelisting can enforce least-privilege boundaries between application services and the graph, but only if the default PUBLIC role and custom procedure execution are explicitly constrained.
11 Jan 2026, 22:41 UTC

When an application service connects to Neo4j with administrative credentials, a compromised dependency or injection flaw becomes a full graph takeover. The practical takeaway is that Neo4j Enterprise Edition's role-based access control (RBAC) combined with procedure whitelisting can enforce least-privilege boundaries between application services and the graph, but only if the default PUBLIC role and custom procedure execution are explicitly constrained.
Requirements and Version Assumptions
This architecture requires Neo4j Enterprise Edition. Community Edition does not include RBAC, so the role and privilege model described here is unavailable. The examples below assume Neo4j 5.x; role names and default privileges differ in 4.x, particularly around the PUBLIC role. Verify behavior against your target version before deploying.
Smallest Suitable Design
Start with two application personas rather than one shared login: a read-only analytics persona and a transactional writer persona. Create dedicated database users for each service; never reuse the default neo4j administrative account for application traffic.
Use built-in roles where they fit. Neo4j Enterprise ships with roles such as reader, publisher, and editor that map to common least-privilege patterns. For example, an analytics service can be assigned the reader role, while a transactional service that creates and updates nodes can use publisher. Avoid granting the admin role to application services; admin bypasses many security constraints and should be reserved for operators.
Procedure whitelisting tightens the boundary further. The setting dbms.security.procedures.roles in neo4j.conf restricts which custom procedures and functions a role may execute. This prevents privilege escalation through APOC or user-defined procedures that might otherwise expose administrative capabilities.
Example configuration
Suppose an analytics service needs only APOC metadata procedures. In neo4j.conf (edit as a user with file-system access to the Neo4j configuration directory; restart Neo4j afterward):
dbms.security.procedures.roles=reader:apoc.meta.*
This allow-list entry permits the reader role to execute procedures matching apoc.meta.* and blocks everything else. A missing entry silently blocks execution, which can cause runtime failures that are easy to miss during development.
Trust and Data Boundaries
Separate read-only analytics workloads from transactional writers. In Neo4j 5 and later, the PUBLIC role grants baseline privileges to all users, so explicit DENY rules or restricted role assignments are required to tighten default access. Combining reader roles with read replicas reduces blast radius and lock contention: analytics queries run against a replica, leaving the primary free for writes.
Data boundaries should follow the same pattern. The writer persona holds GRANT privileges only on the labels and relationship types it must modify. The reader persona holds no write privileges at all. If a service needs both read and write access, split it into two connections or two deployments rather than granting a broad role.
Operational Checks
Validate the boundary after deployment and after any role change.
- Confirm role assignments. In the Neo4j Browser or via Cypher (run as a user with
SHOWprivileges, typicallyadmin), executeSHOW ROLESandSHOW USERSto verify that each application user holds only the intended roles. - Test a blocked procedure. Connect as the application user in the Neo4j Browser or via a driver and attempt to invoke a procedure that is not whitelisted. The expected check is an authorization error, confirming the allow-list is active. For example, if only
apoc.meta.*is permitted, callingapoc.cypher.run(...)should fail. - Review the configuration file. Inspect
neo4j.conffordbms.security.procedures.rolesentries and ensure only necessary procedures are listed for each role. - Monitor logs. Check the Neo4j logs for authorization failures after deploying application code that calls custom procedures. A sudden spike in authorization errors often indicates a missing whitelist entry.
Failure Modes
Three failure modes dominate this design.
Accidental privilege escalation. If procedures are unrestricted, an application user with reader might invoke a procedure that executes arbitrary Cypher, effectively gaining write access. Whitelisting closes this path, but only for procedures covered by the rule.
Application outages from whitelist gaps. Because the rule is allow-list based, adding a new procedure call to application code without updating neo4j.conf blocks execution at runtime. This is a hard-to-debug failure because the error appears only when the specific code path runs.
Role definition drift. In a clustered deployment, inconsistent neo4j.conf files across members can cause different servers to enforce different procedure rules. Validate configuration consistency across all cluster members.
Conditions That Would Change the Design
Revisit this architecture under the following conditions.
- Community Edition. Without RBAC, procedure whitelisting and role-based boundaries are unavailable. The fallback is network-level isolation and separate database instances.
- Version migration from 4.x to 5.x. The
PUBLICrole behavior changes between major versions. A design that relied on implicit restrictions in 4.x may need explicitDENYrules after upgrading. - Proliferating custom procedures. If the application depends on many user-defined procedures, the whitelist becomes a maintenance burden. Consider packaging approved procedures into a narrower, versioned library rather than whitelisting broad namespaces.
- Multi-tenant requirements. If different tenants require different graph access within the same database, built-in roles are too coarse. You would need finer-grained privilege management or database-per-tenant isolation.
Limitations and Verification
This design depends on Enterprise Edition features that are version-sensitive. Exact role names, default PUBLIC privileges, and procedure namespaces vary between releases. The configuration example is illustrative; verify the exact procedure namespace and role names against your Neo4j version and APOC version. No output or behavior described here has been tested in your environment.
To check the result in practice, deploy a non-production instance, create the users and roles, apply the whitelist, and run the negative test described above. Confirm that allowed procedures execute and blocked procedures return an authorization error before promoting the configuration to production.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.