← All recipes
Moderne licensed

Track data lineage

Recipe IDorg.openrewrite.analysis.java.datalineage.TrackDataLineageArtifactio.moderne.recipe:rewrite-program-analysis

Tracks the flow of data from database sources to API sinks to understand data dependencies and support compliance requirements. ## Prerequisites for detecting a data flow All of the following conditions must be met for the recipe to report a flow: 1. The source code must contain at least one method call matching a recognized **source** (see below). 2. The source code must contain at least one method call matching a recognized **sink** (see below). 3. The tainted data must propagate from the source to the sink through variable assignments within the same method or via fields across methods in the same compilation unit. 4. No **flow breaker** (see below) may appear on the path between source and sink. 5. The relevant library types (e.g., java.sql.ResultSet, javax.ws.rs.core.Response) must be on the classpath so that OpenRewrite can resolve types. If types are unresolved, method matchers will not trigger and no flows will be detected. ## Recognized sources (database reads) | Category | Classes | | --- | --- | | JDBC | java.sql.ResultSet | | JPA (javax) | javax.persistence.EntityManager, Query, TypedQuery | | JPA (jakarta) | jakarta.persistence.EntityManager, Query, TypedQuery | | Hibernate | org.hibernate.Session, org.hibernate.query.Query | | Spring Data | org.springframework.data.repository.CrudRepository | | Spring JDBC | org.springframework.jdbc.core.JdbcTemplate | | MyBatis | org.apache.ibatis.session.SqlSession, org.mybatis.spring.SqlSessionTemplate | | MongoDB | com.mongodb.client.MongoCollection, org.springframework.data.mongodb.core.MongoTemplate | | Redis | redis.clients.jedis.Jedis, org.springframework.data.redis.core.RedisTemplate, ValueOperations, HashOperations | | Cassandra | com.datastax.driver.core.Session, org.springframework.data.cassandra.core.CassandraTemplate | | Elasticsearch | org.elasticsearch.client.RestHighLevelClient, org.springframework.data.elasticsearch.core.ElasticsearchTemplate | | Heuristic | Any class with Repository, Dao, or Mapper in its name calling methods starting with find, get, query, search, load, fetch, or select | ## Recognized sinks (API responses) | Category | Classes | | --- | --- | | JAX-RS (javax) | javax.ws.rs.core.Response, Response.ResponseBuilder | | JAX-RS (jakarta) | jakarta.ws.rs.core.Response, Response.ResponseBuilder | | Spring MVC | org.springframework.http.ResponseEntity, ResponseEntity.BodyBuilder | | Servlet (javax) | javax.servlet.http.HttpServletResponse, javax.servlet.ServletOutputStream | | Servlet (jakarta) | jakarta.servlet.http.HttpServletResponse, jakarta.servlet.ServletOutputStream | | Java I/O | java.io.PrintWriter, java.io.Writer, java.io.OutputStream | | Jackson | com.fasterxml.jackson.databind.ObjectMapper, com.fasterxml.jackson.core.JsonGenerator | | Gson | com.google.gson.Gson, com.google.gson.JsonWriter | | GraphQL | graphql.schema.DataFetcher, graphql.schema.PropertyDataFetcher | | Spring WebFlux | ServerResponse, reactor.core.publisher.Mono, reactor.core.publisher.Flux | | gRPC | io.grpc.stub.StreamObserver | | WebSocket | javax.websocket.Session, RemoteEndpoint.Basic, jakarta.websocket.*, org.springframework.web.socket.WebSocketSession | ## Flow breakers Flows are broken by methods matching common sanitization patterns (anonymize, redact, mask, encrypt, hash, sanitize, etc.) or authorization checks (isAuthorized, hasPermission, hasRole, etc.).

Single recipeProprietary

Add to your build

Get a download tokenThis recipe is Moderne licensed, so the token must belong to a Moderne customer. It replaces YOUR_DOWNLOAD_TOKEN below.

~/.gradle/gradle.properties

codeGenomeUsername=you@example.com
codeGenomeToken=YOUR_DOWNLOAD_TOKEN

build.gradle.kts

plugins {
    id("org.openrewrite.rewrite") version("latest.release")
}

rewrite {
    activeRecipe("org.openrewrite.analysis.java.datalineage.TrackDataLineage")
}

repositories {
    mavenCentral()
    maven {
        url = uri("https://artifacts.codegenomeproject.org/maven")
        credentials {
            username = providers.gradleProperty("codeGenomeUsername").get()
            password = providers.gradleProperty("codeGenomeToken").get()
        }
    }
}

dependencies {
    rewrite("io.moderne.recipe:rewrite-program-analysis:0.16.0")
}

Then run

./gradlew rewriteRun

Usage

This recipe has no required configuration options. You’ll need the Moderne CLI configured before running the command below.

mod run . --recipe org.openrewrite.analysis.java.datalineage.TrackDataLineage

If the recipe isn’t available locally, install it with:

mod config recipes jar install io.moderne.recipe:rewrite-program-analysis:RELEASE

Data tables

Structured output this recipe can produce.

  • Taint flowRecords taint flows from sources to sinks with their taint types.org.openrewrite.analysis.java.taint.table.TaintFlowTable
  • Source files that had resultsSource files that were modified by the recipe run.org.openrewrite.table.SourcesFileResults
  • Source files that had search resultsSearch results that were found during the recipe run.org.openrewrite.table.SearchResults
  • Source files that errored on a recipeThe details of all errors produced by a recipe run.org.openrewrite.table.SourcesFileErrors
  • Recipe performanceStatistics used in analyzing the performance of recipes.org.openrewrite.table.RecipeRunStats