Recipe Name:
Spring Data Neo4jClient#query is vulnerable to injections
Description:
Spring Data Neo4jClient#query is vulnerable to injections
Level:
error
Language:
  • java
Tags:
  • security
  • Neo4j
  • framework specific
  • OWASP Top 10
  • injection
  • Spring Data
Documentation
Concatenation of untrusted input directly into Neo4J queries can lead to injection attacks. Before
this.neo4jClient
	.query("" +
		"MATCH (movie:Movie {title: '"+title+"'}) " +
		"OPTIONAL MATCH (person:Person)-[r]->(movie) " +
		"WITH movie, COLLECT({ name: person.name, job: REPLACE(TOLOWER(TYPE(r)), '_in', ''), role: HEAD(r.roles) }) as cast " +
		"RETURN movie { .title, cast: cast }"
	)
	.in(database())
	.fetchAs(MovieDetailsDto.class)
	.mappedBy(this::toMovieDetails)
	.one()
	.orElse(null);
After
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("title", title);
this.neo4jClient
	.query("" +
		"MATCH (movie:Movie {title: $title}) " +
		"OPTIONAL MATCH (person:Person)-[r]->(movie) " +
		"WITH movie, COLLECT({ name: person.name, job: REPLACE(TOLOWER(TYPE(r)), '_in', ''), role: HEAD(r.roles) }) as cast " +
		"RETURN movie { .title, cast: cast }"
	)
	.in(database()).bindAll(map)
	.fetchAs(MovieDetailsDto.class)
	.mappedBy(this::toMovieDetails)
	.one()
	.orElse(null);
Recipe
id: neo4j#query-is-vulnerable-to-injection
version: 10
metadata:
  name: Spring Data Neo4jClient#query is vulnerable to injections
  shortDescription: Spring Data Neo4jClient#query is vulnerable to injections
  level: error
  language: java
  enabled: true
  descriptionFile: descriptions/Spring_Data_Neo4jClient_query_is_vulnerable_to_injections.html
  tags: security;Neo4j;framework specific;OWASP Top 10;injection;Spring Data
search:
  methodcall:
    args:
      1:
        type: java.lang.String
        value:
          containsUntrustedInput: true
          trustNonTextualsByDefault: false
    followedBy:
      methodcall:
        name: in
    name: query
    type: org.springframework.data.neo4j.core.Neo4jClient
availableFixes:
- name: Parameterize the query
  actions:
  - parameterize:
      placeholderFormat: ${{{name}}}
      extractUntrustedInput:
        methodsOnObject:
          methods:
          - methodName: put
            args:
              "1": '"{{{name}}}"'
              "2": '{{{.}}}'
          target:
            variable:
              variableName: map
              type: java.util.HashMap<String, Object>
          applyExtraction:
            target: followedByElement
            methodcall: bindAll({{{target-variable}}})
      target: self