Skip to content

Repository files navigation

Thorfinn

Thorfinn

Drop in an APK. Find client-side vulnerabilities. Validate exploitability with AI.


Get Started   Demo   Vulnerabilities   How It Works

Join Discord   Read the Docs

Traces complex Android data flows  ·  Generates and executes PoCs on a connected device or emulator  ·  Produces HTML report with evidence

Thorfinn is an automated Dynamic Application Security Testing framework for Android apps. Given an Android APK, the framework can identify complex Android client-side vulnerabilities, including WebView hijacking, intent redirection, and more, by decompiling the APK and tracing taint flows between sources and sinks.

Unlike scanners that report isolated risky patterns or rely on generic dynamic payloads, Thorfinn traces attacker-controlled data across classes and Android-specific flows such as intents, extras, deep links, startActivity(), and component transitions. It supports configurable sources and sinks, pattern-based checks for common misconfigurations and hardcoded secrets, and Manifest auditing for meaningful permission and component exposure issues.

For all true positive findings, Thorfinn uses the complete taint path and application context to triage the issue, generate targeted proof-of-concept payloads, execute them on the connected device or emulator, and collect runtime evidence. The final report includes the vulnerable flow, affected components, payloads, and validation evidence needed to verify and reproduce real client-side vulnerabilities. We also support multiple LLM providers for triaging findings and generating POCs, including OpenAI, Anthropic and Gemini. We also support GitHub Copilot CLI but the CLI should be conifgured in your system and available in PATH.

Demo

Demo

Vulnerabilities Identified

  • Intent Redirection
  • Implicit Intent Interception
  • WebView Vulnerability
  • Content Provider Path Traversal
  • Content Provider Proxy
  • Arbitrary File Write
  • PendingIntent Redirection
  • Changing Device Settings
  • Dynamic Receiver Registration
  • FileProvider Misconfiguration
  • Hardcoded Secrets
  • Unprotected Exported Components
  • Insecure Application Flags (debuggable, allowBackup, cleartextTraffic)
  • Dangerous / Signature-Level Permissions
  • Permission Name Typos
  • Component Declaration Typos
  • Ecosystem Permission Mistakes
  • ContentProvider readPermission / writePermission Gaps

Quick Start

git clone https://github.com/PhonePe/Thorfinn.git --recurse-submodules
cd Thorfinn
./setup.sh

# add your LLM key and base directory for the project
vim config/config.yml

# plug in a device and go (--config is required)
adb devices
# verify you have device running with target apk installed
java -jar target/Thorfinn.jar com.target.app --config config/config.yml

# big app? running out of heap space limit time for propogation
java -jar target/Thorfinn.jar com.target.app --config config/config.yml --time-limit 300

setup.sh handles Java 17, Maven, JADX, Semgrep, TruffleHog, APKTool, ADB, and Python. Works on macOS (Homebrew) and Linux (apt).

Configuration

After setup, edit the config at config/config.yml:

toolsConfig:
  decompilers: jadx
  analysisTools:
    - taie
    - semgrep
    - permissionChecker
    - truffleHog
  llmProvider: openai                           # supports openai, anthropic, copilot and gemini
  llmApiKey: Bearer YOUR_API_KEY                # Add token with scheme if applicable (e.g. Bearer) otherwise just the token. n/a for copilot
  llmModel: gpt-4                               # Model to use for LLM analysis as per the provider
  llmBaseUrl: https://api.openai.com            # URL for your LLM provider API, n/a for copilot
  taiEAgentEnabled: false                       # flip to true if you reach input token limit in direct flow or else keep it false
  agentLlmApiKey: Bearer YOUR_AGENT_API_KEY     # Used only by TaiE agent mode
  agentLlmModel: gpt-4                          # Used only by TaiE agent mode
  agentLlmBaseUrl: https://api.openai.com       # Used only by TaiE agent mode
  taiEAgentMaxToolResponsePercentage: 30        # Max context % for agent tool responses
  taiEMaxHeapGb: 0                              # Specify heap size here, defaults to 75% of available memory if 0
  taiEOnlyApp: true                             # true = taint analysis only app code including everything bundled into it sdk etc. ; false = whole-program including reading their bodies as well
  ignoredTaiePackages:                          # package prefix for tai-e to exclude from triage being either third party or false positives
    - "com.example.thirdparty."
    - "com.yourorg.analytics."
  ignoredSemgrepPackages:                       # package prefix for semgrep to exclude from triage being either third party or false positives
    - "com.false.positives."

pathConfigs:
  baseDirectory: BASE_DIRECTORY_FOR_PROJECT     # Replace this with your base directory path for thorfinn
  decompiledApkPath: /resources/decompiled_apks/
  taiePath: /resources/tools/tai-e-all-0.5.4-SNAPSHOT.jar
  androidPlatformsPath: /resources/android-platforms/
  taieOutputPath: /resources/taie_output/
  taintConfigPath: /config/taint_config.yml
  permissionCheckerPath: /resources/tools/permissionChecker.py
  semgrepRulesPath: /resources/tools/semgrep-rules/
  outputPath: /resources/output/

Important

  • taiEMaxHeapGb is the maximum heap size for Tai-e analysis. If zero, it will calculate the 75% of available memory and use that as the heap size.
  • ignoredTaiePackages is a list of packages prefix for tai-e that you may want to ignore from verification due to being 3rd party or false positives.
  • ignoredSemgrepPackages is a list of packages prefix for semgrep that you may want to ignore from verification due to being 3rd party or false positives.
  • taiEOnlyApp by default true (strongly recommended for big applications) makes taint analysis only analyze the app code and everything bundled into it (e.g. SDKs). If you want to analyze the whole program including reading their bodies as well, set taiEOnlyApp to false in config.yml but this causes issues on larger APKs.
  • llmProvider specifies the LLM you want to use for triaging the findings reported by various tools. Currently, we support OpenAI, Gemini and Anthropic. However, agent mode only supports OpenAI. We also support GitHub Copilot CLI but the CLI should be conifgured in your system and available in PATH.

Usage

java -jar target/Thorfinn.jar <package-name> --config config/config.yml or <custom path> [options]

Arguments:
  <package-name>              Android package name of the target app (must be installed on connected device)

Options:
  -c, --config <path>               Path to config.yml (required)
  -t, --time-limit <seconds>        Time limit for CPG/taint analysis
  -r, --report-path <path>          If given the LLM calls for the findings in previous report will be skipped and same findings will be executed based on POC
  -d, --diff-report-path <path>     If given the findings which are already in report are completely skipped from final report and only new findings are included
  -y, --auto-approve                Auto-approve every LLM-generated POC command without prompting
  -s, --skip-verify                 Skip execution of all LLM-generated POC commands
  -h, --help                        Show this help message

Thorfinn requires a configuration file for LLM settings, taint rules, tool paths, and verification options. Pass it using the --config flag; relative paths are resolved from the current working directory.

Tip

  • Large apps / out of heap (--time-limit) use this option to cap the time spent on propagation. This reduces the number of findings as application propagation is cut short, but issues will still be discovered on the paths that have been fully analyzed.
  • Skip re-triage (--report-path): each run generates a JSON and an HTML report, and the JSON report contains a signature for each finding. Pass a previous report with --report-path to skip LLM triage for findings whose signature matches the previous report; their POC commands are still executed.
  • Diff scan (--diff-report-path): pass a previous report to skip findings whose signature already exists in it, so only new findings are included in the final report. However, the JSON report contains all the findings since it may be required to run again for diff scans later or creating automation around it to store and update vulnerabilities. For tracking, each issue has app version in which vulnerability was introduced and these are maintained based on the version present in report.

POC Verification (LLM-generated commands)

After static analysis and LLM triage, Thorfinn generates a proof-of-concept using adb command for each finding it deems a TRUE POSITIVE and verifies it on the connected device. Because these commands are generated by an LLM and executed against a real device, you control whether each command runs:

Mode Flag Behaviour
Interactive (default) (none) Each POC command is shown in a review box and you approve it with Y / decline with N before it runs.
Auto-approve -y, --auto-approve Every POC command is executed automatically without prompting.
Skip -s, --skip-verify No POC commands are executed; findings are reported without dynamic verification.

In the default interactive mode you'll see a prompt like this for each command, and nothing runs until you respond:

╔══════════════════════════════════════════════════════════════════════════════╗
║               LLM-GENERATED POC - REVIEW BEFORE EXECUTION                    ║
╠══════════════════════════════════════════════════════════════════════════════╣
║ Vulnerability : WebView Vulnerability                                        ║
║ Source        : vulnerable.example.app.MainActivity                          ║
║ Sink          : vulnerable.example.app.WebViewActivity                       ║
╠══════════════════════════════════════════════════════════════════════════════╣
║ Command:                                                                     ║
║   adb shell "am start -n vulnerable.example.app/.MainActivity ..."           ║
╚══════════════════════════════════════════════════════════════════════════════╝
[?] Execute this command on device? (Y/N):

⚠️ Review commands carefully in interactive mode. --auto-approve runs every LLM-generated command against your device without review - use it only on test devices/apps you trust.

Examples:

# Interactive review (default) - approve or skip each command
java -jar target/Thorfinn.jar com.target.app --config config/config.yml

# Run everything unattended
java -jar target/Thorfinn.jar com.target.app --config config/config.yml --auto-approve

# Static findings only, never touch the device with POCs
java -jar target/Thorfinn.jar com.target.app --config config/config.yml --skip-verify

How It Works

flowchart TD
    A["Pull APK from Device"] --> B["Decompile (JADX / APKTool)"]
    B --> C["Manifest Analysis"]
    C --> D["Vulnerability Analyzers"]
    
    D --> E1["Tai-e"] & E2["Semgrep"] & E3["TruffleHog"] & E4["PermissionChecker"]
    
    E1 & E2 & E3 & E4 --> F["LLM Triage"]
    
    F -->|True Positive| G["⚡ Generate & Verify POC"]
    F -->|False Positive| X["Dropped"]
    
    G --> H["HTML Report"]
Loading

Final Report

For validated findings, Thorfinn reports:

  • Vulnerability type and severity
  • Source and sink details
  • Complete taint path
  • Affected Android components
  • Relevant Manifest configuration
  • Generated proof-of-concept payload
  • Device or emulator execution output
  • Runtime evidence of exploitability
  • Context required to manually reproduce and validate the issue

Documentation

Read the detailed documentation for installation, configuration, rule customization, supported checks, and architecture:

phonepe.github.io/thorfinn

Tools Credits

Responsible Use

Thorfinn is intended for authorized security testing, research, and bug bounty programs where you have permission to assess the target application.

Do not use Thorfinn against applications, devices, or environments without explicit authorization.

License

Thorfinn is licensed under the Apache License 2.0.

About

Automated DAST for Android Apps

Resources

Stars

155 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages