CLI tool
secure-software-engineering/FlowDroid avatar
secure-software-engineering/FlowDroid

FlowDroid: a static data flow tracker for Android and Java, built on Soot

FlowDroid Static Data Flow Tracker

1,274 stars323 forksJavaLGPL-2.1

At a glance

What is it?
FlowDroid statically computes data flows in Android apps and Java programs, tracking where sensitive data comes from and where it can leak to, and it ships both as a command line tool and as a library. Its cost is the one every whole program analysis has: it is slow on large apps, which is why the tool exposes precision and recall tradeoffs and three separate timeouts.
Who is it for?
FlowDroid fits a security researcher or a privacy audit team that needs to know where sensitive data enters an Android app and where it leaves, and that can tolerate a whole program analysis on the code in question. It is the wrong tool for a fast per-commit gate, since the README is explicit that it takes a very long time for large apps, and the wrong tool if you need a source and sink model for a domain the default SourcesAndSinks.txt does not cover.
Can I use it commercially?
Yes, with conditions. LGPL-2.1 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
Is it still maintained?
Yes. The repository last received commits 26 days ago.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What it computes, and who it is for

FlowDroid statically computes data flows in Android apps and Java programs. The stated goal is to provide researchers and practitioners with a tool and library on which they can base their own research projects and product implementations, and the project says it is happy to see FlowDroid now widely used in academia as well as in industry.

The distinction between a tool and a library is the first thing to understand, because it determines how you would use it. As a tool, it is a whole program analysis that takes an application and tells you which flows from a source to a sink exist. As a library, it is a set of components you embed in your own analysis, and you are responsible for the configuration around it.

The primary language is Java, the licence is LGPL-2.1, and the default branch is develop. The recent releases are v2.15.1 on 2026-02-23, v2.15 on 2026-02-19 and v2.14.1 on 2024-10-09, so the 2.x line has been stable across those versions with a gap in the middle. The repository is not archived, with the last push on 2026-09-28.

The repository layout reflects the module structure directly, and the module names are the API. There is soot-infoflow/ which is the core library, soot-infoflow-android/ for the Android specific parts, soot-infoflow-summaries/ for the library summaries, soot-infoflow-cmd/ for the command line interface, and soot-infoflow-integration/ for the integration tests. There is also a DroidBench directory and a .gitmodules file, so DroidBench comes in as a submodule, and that matters for the build.

The dependency on Soot is the other structural fact. FlowDroid is built on Soot, the Java bytecode analysis framework, and the build requirements say the current snapshot of Soot must be installed. Soot is what turns class files and Android APKs into a program representation FlowDroid can analyse, and the dependency is on a snapshot rather than a release, which is worth knowing before you plan a reproducible build.

The project is hosted under the secure-software-engineering organisation and its Maven coordinates are de.fraunhofer.sit.sse.flowdroid, which tells you the institutional origin, a Fraunhofer institute.

Getting it, and the three ways to install it

There are three acquisition routes, and the README's advice on all of them is the same: use the latest version unless you have a specific issue that prevents you, and in that case let them know.

The first is Maven Central, where the artifact is under de.fraunhofer.sit.sse.flowdroid. To use it in a Maven build you include three dependencies:

code
    <dependencies>
        <dependency>
            <groupId>de.fraunhofer.sit.sse.flowdroid</groupId>
            <artifactId>soot-infoflow</artifactId>
            <version>2.12.0</version>
        </dependency>
        <dependency>
            <groupId>de.fraunhofer.sit.sse.flowdroid</groupId>
            <artifactId>soot-infoflow-summaries</artifactId>
            <version>2.12.0</version>
        </dependency>
        <dependency>
            <groupId>de.fraunhofer.sit.sse.flowdroid</groupId>
            <artifactId>soot-infoflow-android</artifactId>
            <version>2.12.0</version>
        </dependency>
    </dependencies>

The three artifacts are the three layers, and the version in the snippet is 2.12.0 while the current release is 2.15.1, so the documentation example is a few versions behind. The summaries artifact is the one people miss, because the default StubDroid library summaries are a separate download rather than something compiled in.

The second route is a GitHub release, and the release page contains all pre-built JAR files for each officially published release. The command line tool is a single file either way, the soot-infoflow-cmd-jar-with-dependencies.jar, which is the shaded jar with Soot and everything else bundled. That is the difference between a library dependency and a tool you can run without resolving anything.

The third route is building it yourself, and the requirements are JDK 11 or above, Maven, and the current snapshot of Soot installed. The build has a wrinkle that the README explains clearly: at the first time, FlowDroid needs to be built from the parent module, that is the project's root folder, because the modules depend on each other. The full test suite takes around 30 minutes, so the recommendation is to disable the tests when building:

shell
mvn install -DskipTests

Running the build with tests enabled needs more: JDK 8 must be installed, the rt.jar must be at the default location, or alternatively placed inside $JAVA_HOME/lib/, the DroidBench submodule must be initialised by cloning with --recursive, and the ANDROID_JARS environment variable must be set to the android platforms directory, typically $HOME/Android/Sdk/platforms/.

The JDK 8 requirement alongside a JDK 11 requirement is a slightly odd combination, and the reason is visible in the list: rt.jar is the Java runtime class library shipped with JDK 8, and the test suite needs it to construct reference analyses. The DroidBench requirement is the same kind of thing, since DroidBench is the benchmark suite of flow problems and the integration tests run against it.

There is also an Eclipse path. The project is worked on in Eclipse, all modules are Eclipse projects and can be imported, and they will appear as Maven projects there, with Eclipse taking care of downloading the dependencies.

Running it, and what a sources and sinks file actually is

The command line invocation is short:

code
java -jar soot-infoflow-cmd/target/soot-infoflow-cmd-jar-with-dependencies.jar \
    -a <APK File> \
    -p <Android JAR folder> \
    -s <SourcesSinks file>

The -p argument is the platforms directory inside your Android SDK installation folder, so FlowDroid can resolve the Android framework classes to analyse against. The -s argument is the file that defines the model, and the README explains the concept carefully: the definition file for sources and sinks defines what shall be treated as a source of sensitive information and what shall be treated as a sink that can possibly leak sensitive data to the outside world. These definitions are specific to your use case, and if you are looking for privacy issues you can use the default file SourcesAndSinks.txt in the soot-infoflow-android folder as a starting point.

That paragraph is the conceptual heart of the tool. FlowDroid does not decide what is sensitive, it is told. The source and sink model is your policy, expressed as a file, and the analysis finds the paths through the program from one to the other. Which means the quality of the result is bounded by the quality of that model, and a project that wants to track a domain specific secret has to write the model itself.

For the other options you can run the tool with the --help option, or read the MainClass.initializeCommandLineOptions() method in the source, in the soot-infoflow-cmd module. Pointing at a method rather than a flag list is a reasonable choice for a tool with this many options.

The library path is the other half of the documentation, and it is where the customisation lives. If you want to implement something and need a data flow tracker as a component, you are better off integrating the FlowDroid modules as JAR files, while if you just need the results quickly you run the command line interface. So the README itself is steering you towards the library for anything beyond a one-off analysis.

The library entry point is four lines:

code
SetupApplication app = new SetupApplication(androidJarFolder, apkPath);
app.setTaintWrapper(new SummaryTaintWrapper(new LazySummaryProvider("summariesManual")));
InfoflowResults results = app.runInfoflow();

You replace the androidJarFolder placeholder with the location of the platforms directory in your Android SDK, and apkPath with the full path of the APK file. The results are accessible via the InfoflowResults class.

The middle line is the one that matters. The data flow analysis uses the default StubDroid library summaries, and the taint wrapper is the object that decides where those summaries come from. Here it is a SummaryTaintWrapper over a LazySummaryProvider pointing at summariesManual, which is the mechanism for pointing FlowDroid at your own set of library summaries instead of the default ones. If your application uses libraries the default summaries do not model accurately, that is the hook you use, and it is why the library path exists at all rather than the tool.

Why the source and sink model is the real interface

It is worth spending a moment on why the sources and sinks file matters more than any flag, because it is the thing that determines whether a FlowDroid result is useful.

The tool does not contain a notion of what is sensitive. There is no built-in list of dangerous APIs that it applies. Instead, the caller supplies a definition file, and the analysis answers one question with that file: given these sources and these sinks, what paths exist from one to the other.

That design has a consequence that is easy to miss when you read the feature list. FlowDroid is not an Android security scanner that finds problems. It is an engine that finds flows, and whether a flow is a problem is entirely a function of the model you gave it. A source that is a cursor position and a sink that is a log statement is a privacy leak. A source that is a cursor position and a sink that is a log statement in a debug build is not. The tool cannot tell the difference, and it is not trying to.

The default file, SourcesAndSinks.txt in the soot-infoflow-android folder, is a starting point for privacy issues, and the README recommends it for that case. But it is a starting point rather than a policy, and for a specific product with a specific threat model, the file you write is the analysis you get.

The same reasoning applies on the Java side. FlowDroid handles Java programs as well as Android apps, and the library path is the natural way to use it for those, because the summary and taint model is configured in code. The command line with -s is the quick way, and the library is the way to build a product on top of it.

There is one more dimension to the model, which is the library summaries. The analysis uses the default StubDroid library summaries, which model what each library method does to the data it is given. If a library method in your dependency tree is not in the default summaries, FlowDroid does not know what it does with the tainted data, and the flow stops there or is misjudged. That is the reason the taint wrapper and the lazy summary provider exist in the library API, and the reason a serious use of FlowDroid usually involves writing summaries for the libraries your code actually depends on.

So the practical order of work for an evaluation is: decide the sources and sinks for your domain, check which of your dependencies the default summaries cover, and only then run the analysis and look at the flows. Running it first and interpreting the output afterwards inverts the process and produces results you cannot act on.

The performance problem, and the four flags that address it

This is the part of FlowDroid that anyone running it on a real codebase needs to know about, and the README is unusually direct about it.

For some apps, FlowDroid will take very long for large apps. There are various options with which you can configure a tradeoff between performance, precision and recall.

The precision options come first. -ns does not track taints on static fields and disregards static initializers. -ne does not track exceptional flows. Both of those buy speed by losing flows, and they are the same two tradeoffs every taint analysis tool offers, because static fields and exception handling are exactly where the analysis cost blows up.

The timeout options are the more interesting mechanism, because there are three of them and they cover the three stages of the analysis:

-dt N aborts the data flow analysis after N seconds and returns the results obtained so far. -ct N aborts the callback collection during callgraph construction after N seconds and continues with the incomplete callgraph constructed so far. -rt N aborts the result collection after N seconds and returns the results obtained so far.

And the note about them is the operational detail: timeouts are additive, and all three stages must complete or run into a timeout for the tool to return and deliver results.

That additive property has a practical consequence. The stages run in sequence, and the callgraph construction is the expensive one, so setting -ct low does not bound the total runtime to that value, it bounds one stage of a three stage pipeline. A user who sets -ct 60 and -dt 60 has not capped the run at sixty seconds.

It also explains why the timeout is expressed as abort-and-return-partial rather than as a hard budget. A partial callgraph is not a correct callgraph, so the flows found under it are a subset of the real ones, and the tool is trading recall for the guarantee of returning something. Whether that trade is acceptable depends entirely on what you are using the result for, which is why the flags are separate per stage rather than one global timeout.

The stage structure also tells you where the cost is. Callgraph construction, which means resolving callbacks, is the classic bottleneck in whole program analysis of Android apps, because the Android framework's callback patterns are hard to resolve statically. The -ct flag exists precisely because that stage is the one that hangs, and the fact that the tool offers a separate budget for it rather than one global timeout is the design telling you where the pain is.

Editorial conclusion

FlowDroid fits a security researcher or a privacy audit team that needs to know where sensitive data enters an Android app and where it leaves, and that can tolerate a whole program analysis on the code in question. It is the wrong tool for a fast per-commit gate, since the README is explicit that it takes a very long time for large apps, and the wrong tool if you need a source and sink model for a domain the default SourcesAndSinks.txt does not cover. Before adopting, decide whether you need the library or the command line, because the library is the path that scales and the command line is the path that is convenient.

Frequently asked questions

What does FlowDroid do and who is it for?

It statically computes data flows in Android apps and Java programs, tracking where sensitive data originates and where it can leak to. The goal is to give researchers and practitioners a tool and library they can build their own research projects and product implementations on, and it is used in both academia and industry.

How do I run the FlowDroid command line tool?

Run java -jar on soot-infoflow-cmd-jar-with-dependencies.jar with -a for the APK file, -p for the Android platforms directory in your SDK, and -s for a sources and sinks definition file. The -s file defines what counts as a source of sensitive information and what counts as a sink that can leak it, and the default SourcesAndSinks.txt is a starting point for privacy issues.

How can I make FlowDroid faster on a large app?

Use -ns to not track taints on static fields and disregard static initializers, and -ne to not track exceptional flows, both of which trade precision for speed. There are also three timeouts, -dt for the data flow analysis, -ct for the callback collection during callgraph construction, and -rt for the result collection, each of which returns partial results. The timeouts are additive, so all three stages must complete or time out.

How do I build FlowDroid from source?

You need JDK 11 or above, Maven, and the current snapshot of Soot installed. Build from the parent module at the project root, and since the full test suite takes around 30 minutes, use mvn install -DskipTests. Running the tests additionally needs JDK 8, rt.jar at the default location, the DroidBench submodule initialised with --recursive, and the ANDROID_JARS environment variable set.

Official sources

  1. Issues
  2. License: LGPL-2.1
  3. README
  4. Releases
  5. secure-software-engineering/FlowDroid on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/secure-software-engineering-flowdroid.svg)](https://hysenlabs.com/projects/secure-software-engineering-flowdroid)

Was this useful?