npx skills add ...
npx skills add neo4j-contrib/neo4j-skills --skill neo4j-security-skill
Programmatic security management in Neo4j — RBAC/ABAC, user lifecycle (CREATE/ALTER/DROP USER),
npx skills add neo4j-contrib/neo4j-skills --skill neo4j-security-skill
SHOW PRIVILEGES)neo4j-cypher-skillneo4j-cli-tools-skillneo4j-driver-*-skillBefore 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 RULENever auto-execute privilege changes. Show exact Cypher, annotate impact, get "yes".
All security Cypher runs against the system database:
Tags are arbitrary strings on the native user object, readable in ABAC rules via abac.native.user_tags().
SET/ADD/REMOVE TAG[S] requires SET USER METADATA; reading tag values requires SHOW USER METADATA:
SHOW USERS WITH AUTH AS COMMANDS exposes credentials. Use only for secured backup/restore handling. Prefer SHOW USERS AS COMMANDS when auth material is not required. Never paste auth-export output into plaintext docs, logs, tickets, or source control.
| 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 user tags [2026.06] | GRANT USER METADATA 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 |
Restrict read access to individual properties:
Property-based pattern matching (sub-graph access):
value IN n.listProp — list property contains valuen.prop IN [v1, v2] — scalar-against-listPBAC edge cases and export patterns → references/privilege-reference.md
Constraints:
FOR pattern applies to read privileges only — not writen.prop <op> <literal> or maintain a scalar flag propertyTRAVERSE rules cost more than READABAC grants roles dynamically from OIDC/JWT claims or native user tags rather than explicit GRANT ROLE ... TO user.
Unlisted provider → its accessor function (abac.oidc.user_attribute(), abac.native.user_tags()) unavailable and rules referencing it fail (no silent default).
Native users [2026.06+]: tag native DB users (see User tags) and match tags in rules via abac.native.user_tags() — no OIDC required:
❌ Never condition on tag absence: NOT ('restricted' IN abac.native.user_tags()) — any user created without tags satisfies it, escalating privileges.
✅ Require presence of a tag: 'unrestricted' IN abac.native.user_tags().
Notes:
abac.oidc.user_attribute(); native user tags via abac.native.user_tags() [2026.06+]. LDAP has no accessor function — tag the LDAP user's native user object insteadREAD only, granted on the virtual database [2026.07+, not on Aura] — see references/privilege-reference.md| 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;
Config changes require server restart. Roles referenced in mappings must exist in Neo4j (native or created via Cypher).
CREATE ROLE ... IF NOT EXISTSSHOW ROLE ... PRIVILEGES AS COMMANDS to verifyGRANT ROLE ... TO ...SHOW USER ... PRIVILEGES AS COMMANDSFull privilege syntax → references/privilege-reference.md