Skill v1.0.1
currentAutomated scan100/100+3 new
name: neo4j-security-skill description: Programmatic security management in Neo4j — RBAC/ABAC, user lifecycle (CREATE/ALTER/DROP USER), role lifecycle (CREATE/GRANT ROLE/DROP ROLE), privilege grants and denies (GRANT/DENY/REVOKE on graph, database, DBMS), property-level access control, sub-graph access control, SHOW PRIVILEGES inspection, and auth provider config reference (LDAP, OIDC/SSO). Use when an agent needs to manage users, roles, or privileges programmatically via Cypher on the system database. Does NOT handle Cypher query writing — use neo4j-cypher-skill. Does NOT handle cluster ops or backups — use neo4j-cli-tools-skill. Property-level security and ABAC require Enterprise Edition. allowed-tools: Bash WebFetch version: 1.0.1
When to Use
- Creating, altering, suspending, or dropping users
- Creating roles, granting/revoking role membership
- Granting/denying/revoking graph, database, or DBMS privileges
- Inspecting current privileges (
SHOW PRIVILEGES) - Implementing property-level access control (read/write per property)
- Setting up ABAC rules against OIDC claims
- Referencing LDAP/SSO auth provider configuration
When NOT to Use
- Writing Cypher queries against application data →
neo4j-cypher-skill - Cluster ops, backups, server config →
neo4j-cli-tools-skill - Driver connection setup →
neo4j-driver-*-skill
MCP Write Gate — MANDATORY
Before executing ANY of the following, show the planned command and wait for explicit confirmation:
CREATE USER/ALTER USER/DROP USERCREATE ROLE/DROP ROLEGRANT/DENY/REVOKE(any privilege)CREATE AUTH RULE/DROP AUTH RULE
Never auto-execute privilege changes. Show exact Cypher, annotate impact, get "yes".
Execution Context
All security Cypher runs against the system database:
// Neo4j auto-routes CREATE/ALTER/SHOW USER|ROLE|PRIVILEGE to system// If using cypher-shell: cypher-shell -d system// If using driver: use database="system"
1. User Management
Create user
CREATE USER alice SET PASSWORD 'secret' CHANGE NOT REQUIRED;// CHANGE REQUIRED (default): forces password change on first login// CHANGE NOT REQUIRED: password valid immediately// SET STATUS ACTIVE (default) | SUSPENDED
Parameterised password (preferred in scripts)
CREATE USER $username SET PASSWORD $password CHANGE NOT REQUIRED;
Alter user
ALTER USER alice SET PASSWORD $newPw CHANGE NOT REQUIRED;ALTER USER alice SET STATUS SUSPENDED; // lock accountALTER USER alice SET STATUS ACTIVE; // unlockALTER USER alice SET HOME DATABASE mydb; // default db on connectALTER USER alice IF EXISTS SET PASSWORD $pw; // safe if missing
Show users
SHOW USERS YIELD username, roles, passwordChangeRequired, suspended, homeDatabaseWHERE suspended = falseRETURN username, roles ORDER BY username;
Drop user
DROP USER alice IF EXISTS;
2. Role Management
Create / drop role
CREATE ROLE analyst;CREATE ROLE analyst IF NOT EXISTS;DROP ROLE analyst IF EXISTS;
Assign / remove roles
GRANT ROLE analyst TO alice;GRANT ROLE analyst, writer TO alice, bob; // bulkREVOKE ROLE analyst FROM alice;
Inspect roles
SHOW ROLES YIELD role, member ORDER BY role;SHOW ROLE analyst PRIVILEGES AS COMMANDS; // returns runnable GRANT commandsSHOW POPULATED ROLES YIELD role; // only roles with members
3. Privilege Decision Table
| Goal | Command | |
|---|---|---|
| Allow db connection | GRANT ACCESS ON DATABASE mydb TO analyst | |
| Read all graph data | GRANT MATCH {*} ON GRAPH mydb ELEMENTS * TO analyst | |
| Read specific label | GRANT MATCH {*} ON GRAPH mydb NODES Person TO analyst | |
| Read specific rel type | GRANT MATCH {*} ON GRAPH mydb RELATIONSHIPS KNOWS TO analyst | |
| Read one property | GRANT READ {email} ON GRAPH mydb NODES Person TO analyst | |
| Traverse but hide properties | GRANT TRAVERSE ON GRAPH mydb NODES Person TO analyst | |
| Write (create/set) | GRANT WRITE ON GRAPH mydb TO writer | |
| Create nodes only | GRANT CREATE ON GRAPH mydb NODES Person TO writer | |
| Delete nodes only | GRANT DELETE ON GRAPH mydb NODES Person TO writer | |
| Execute procedure | GRANT EXECUTE PROCEDURE apoc.* TO analyst | |
| Execute function | GRANT EXECUTE USER DEFINED FUNCTION apoc.* TO analyst | |
| All on one db | GRANT ALL ON DATABASE mydb TO dba | |
| Full DBMS admin | GRANT ALL ON DBMS TO dba | |
| Manage users | GRANT USER MANAGEMENT ON DBMS TO secadmin | |
| Manage roles | GRANT ROLE MANAGEMENT ON DBMS TO secadmin | |
| Schema changes | GRANT CREATE ELEMENT TYPES ON DATABASE mydb TO schemaadmin |
DENY overrides GRANT
// Analyst can read Person but NOT the ssn propertyGRANT MATCH {*} ON GRAPH mydb NODES Person TO analyst;DENY READ {ssn} ON GRAPH mydb NODES Person TO analyst;
REVOKE removes a specific grant or deny
REVOKE GRANT READ {email} ON GRAPH mydb NODES Person FROM analyst;REVOKE DENY READ {ssn} ON GRAPH mydb NODES Person FROM analyst;REVOKE MATCH {*} ON GRAPH mydb NODES Person FROM analyst; // removes both grant+deny
4. Common Role Patterns
Read-only analyst
CREATE ROLE analyst IF NOT EXISTS;GRANT ACCESS ON DATABASE mydb TO analyst;GRANT MATCH {*} ON GRAPH mydb ELEMENTS * TO analyst;GRANT EXECUTE PROCEDURE apoc.* TO analyst;
Write role (no admin)
CREATE ROLE writer IF NOT EXISTS;GRANT ACCESS ON DATABASE mydb TO writer;GRANT MATCH {*} ON GRAPH mydb ELEMENTS * TO writer;GRANT WRITE ON GRAPH mydb TO writer;
Read-only on specific labels only
CREATE ROLE limited_reader IF NOT EXISTS;GRANT ACCESS ON DATABASE mydb TO limited_reader;GRANT TRAVERSE ON GRAPH mydb ELEMENTS * TO limited_reader; // can traverseGRANT MATCH {*} ON GRAPH mydb NODES Person TO limited_reader; // Person props visibleGRANT MATCH {*} ON GRAPH mydb NODES Company TO limited_reader; // Company props visible// Other labels: traversable but properties invisible
DBA role (full admin)
CREATE ROLE dba IF NOT EXISTS;GRANT ALL ON DBMS TO dba;GRANT ALL ON DATABASE * TO dba;
5. Property-Level Access Control (Enterprise)
Restrict read access to individual properties:
// Grant read on all Person props, then deny sensitive onesGRANT MATCH {*} ON GRAPH mydb NODES Person TO analyst;DENY READ {ssn, dateOfBirth} ON GRAPH mydb NODES Person TO analyst;
Property-based pattern matching (sub-graph access):
// Only see Person nodes where classification = 'public'GRANT MATCH {*} ON GRAPH mydbFOR (n:Person) WHERE n.classification = 'public'TO analyst;// Block access to classified nodesDENY MATCH {*} ON GRAPH mydbFOR (n) WHERE n.classification <> 'UNCLASSIFIED'TO regularUsers;
Constraints:
FORpattern applies to read privileges only — not write- Each property-based privilege restricted by a single property
- Performance overhead scales with number of rules;
TRAVERSErules cost more thanREAD - Ensure the property used for rules cannot be modified by the restricted role
6. ABAC — Attribute-Based Access Control (Enterprise + OIDC)
ABAC grants roles dynamically from JWT/OIDC claims rather than explicit GRANT ROLE ... TO user.
Prerequisites
# neo4j.confdbms.security.abac.authorization_providers=<oidc-provider-alias>
Create auth rule
CREATE AUTH RULE salesRuleSET CONDITION abac.oidc.user_attribute('department') = 'sales';GRANT ROLE analyst TO AUTH RULE salesRule;
Compound conditions
CREATE OR REPLACE AUTH RULE seniorRuleSET CONDITION abac.oidc.user_attribute('department') = 'engineering'AND abac.oidc.user_attribute('level') >= 5;GRANT ROLE senior_engineer TO AUTH RULE seniorRule;
Manage auth rules
SHOW AUTH RULES YIELD ruleName, condition, roles;ALTER AUTH RULE salesRule SET ENABLED false; // disable without droppingRENAME AUTH RULE salesRule TO salesDeptRule;DROP AUTH RULE salesDeptRule;REVOKE ROLE analyst FROM AUTH RULE salesRule;
Notes:
- Missing claims evaluate to NULL → rule condition false → role not granted
- Rules apply immediately to existing sessions when claims are already loaded
- ABAC works only with OIDC providers (not native or LDAP)
7. SHOW PRIVILEGES Patterns
// All privileges in the systemSHOW PRIVILEGES YIELD *;// Privileges for a specific user (as runnable commands)SHOW USER alice PRIVILEGES AS COMMANDS;// Privileges for a specific roleSHOW ROLE analyst PRIVILEGES YIELD privilege, action, resource, graph, segment;// Find who has access to a databaseSHOW PRIVILEGES YIELD *WHERE graph = 'mydb'RETURN role, action, resource, segment ORDER BY role;// Find all DENY rulesSHOW PRIVILEGES YIELD *WHERE access = 'DENIED'RETURN role, action, resource, segment;
8. Built-in Roles (do not drop)
| Role | Scope | |
|---|---|---|
admin | Full DBMS + all databases | |
architect | Schema changes + write on all databases | |
publisher | Write on all databases | |
editor | Write excluding schema changes | |
reader | Read-only on all databases | |
public | All users implicitly; default home database access |
Assign built-in roles: GRANT ROLE reader TO alice;
9. Auth Provider Config Reference (operational — not Cypher)
Native (default)
dbms.security.auth_enabled=truedbms.security.auth_max_failed_attempts=3 # lockout threshold
LDAP
dbms.security.auth_provider=ldapdbms.security.ldap.host=ldap://ldap.example.comdbms.security.ldap.authentication.mechanism=simpledbms.security.ldap.authentication.user_dn_template=uid={0},ou=users,dc=example,dc=comdbms.security.ldap.authorization.group_membership_attributes=memberOfdbms.security.ldap.authorization.group_to_role_mapping=\"cn=analysts,ou=groups,dc=example,dc=com" = analyst;\"cn=admins,ou=groups,dc=example,dc=com" = admin
OIDC / SSO (Okta, Auth0, Entra ID)
dbms.security.oidc.<alias>.display_name=Oktadbms.security.oidc.<alias>.auth_flow=pkcedbms.security.oidc.<alias>.well_known_discovery_uri=https://example.okta.com/.well-known/openid-configurationdbms.security.oidc.<alias>.audience=neo4jdbms.security.oidc.<alias>.claims.username=emaildbms.security.oidc.<alias>.claims.groups=groupsdbms.security.oidc.<alias>.authorization.group_to_role_mapping=\"neo4j-analysts" = analyst;\"neo4j-admins" = admin
Config changes require server restart. Roles referenced in mappings must exist in Neo4j (native or created via Cypher).
Checklist — New Role Setup
- [ ] Determine required operations: read / write / admin
- [ ] Identify target database(s) and graph scope (all labels vs specific)
- [ ] Identify any properties that must be hidden (→ DENY READ)
- [ ] Create role:
CREATE ROLE ... IF NOT EXISTS - [ ] Grant ACCESS on database
- [ ] Grant MATCH / TRAVERSE / WRITE as needed
- [ ] Apply DENY for restricted properties
- [ ] Run
SHOW ROLE ... PRIVILEGES AS COMMANDSto verify - [ ] Assign to users:
GRANT ROLE ... TO ... - [ ] Test with
SHOW USER ... PRIVILEGES AS COMMANDS
Full privilege syntax → references/privilege-reference.md