How to sanitize inputs to prevent CYPHER injection?

Context: neo4j Javascript driver

Since we are not allowed to use parameters for label names, relationship types, or property keys, the convenient thing to do when building a dynamic query would be to use string interpolation to insert the node label name (for instance) at runtime.

In this knowledge base article, we are warned that this leaves us open to CYPHER injection and so we should sanitize our inputs. But I can't find anything in the docs about specifically how to "sanitize inputs". Can someone explain how to do that?

That article also says "there are some things in Cypher that cannot be parameterized, such as node labels and relation types. There are some APOC Procs that can help (and should be used if so)".

Does anyone know which APOC Procs they are referring to? And how they help with this issue?

@GemLamont Thank you!

I am curious, how do I find out which ones of these apoc procedures are safe and which ones are vulnerable to CYPHER injection? The docs don't seem to mention anything about that.

Can you explain why the first two examples you cite are not safe to use with user input? Does that mean they are still vulnerable to CYPHER injection?

Hi there!

Some useful APOC procedures to help you out include:

apoc.cypher.doit - Write and Read (https://neo4j.com/docs/apoc/current/overview/apoc.cypher/apoc.cypher.doIt)

apoc.cypher.run - Read only (https://neo4j.com/docs/apoc/current/overview/apoc.cypher/apoc.cypher.run/)

These 2 do string concatenation still, but in the query. The idea is you pass in Labels and Types in a safer way by using Labels and Types that are already existing in the db. Note: It is still not safe to use user input for these.

If you need to refactor nodes or relationships then the apoc.refactor.* procedures may be of interest as well as they also provide the ability to use dynamic labels and types. In this case APOC handles the string sanitization for you. (https://neo4j.com/docs/apoc/current/overview/apoc.refactor/)

Hope this helps :slightly_smiling_face:

Hi again :slightly_smiling_face:

Anything that uses string building is vulnerable to Cypher Injection if no sanitisation is used. For the case with the APOC procedures I suggested here is an example to help you out.

Let’s say you send in a query where you have a parameter “label” (The following query is not very useful, but just for show!)

If the param called label is:

:param label => "Person"
CALL apoc.cypher.doIt(
"MATCH (m:`" + $label +"`)" +
"RETURN m.prop", {})
YIELD value
RETURN value

Then this makes APOC run the query:

MATCH (m:`Person`)
RETURN  m.prop

If the param you sent in was using raw user input, and it looked like:

:param label => "Person`) MATCH (a) DETACH DELETE a //"

This runs:

MATCH (m:`Person`) MATCH (a) DETACH DELETE a //RETURN  m.prop

Which will delete everything! And comment out the rest of the query (similar to what the article you showed linked).

So, as you can see, it has the same vulnerabilities as normal Cypher. That is why these procedures are not recommended to be used with user input.

These are however useful for using dynamic labels, types or props in cases where the name for those does not come from user input and therefore doesn’t pose the same risk. For example if you provide the Strings yourself as you know what they contain!

APOC provides some sanitisation for procedures where labels/types are directly passed in.

I believe these are found in

So the only APOC procedures and functions that are safe are ones that directly take a label, type or prop name as input. If it takes a string that is a query, then we can’t do sanitisation on it, making it vulnerable.

Hope this helps :slightly_smiling_face: