JANUS: Agentic Cross-Language Fuzzing Harness Generation for Android Native Libraries

arXiv:2610.30218 · cs.SE, cs.CR · Submitted 2026-10-21 · Read on arXiv

Listen

Radio episode about this paper

Transcript

Introduction to the show: ident: Security Radio. Generated commentary on the latest security and cryptography papers.

Nadia: I'm Nadia.

Elias: And I'm Elias, here with Priya.

Nadia: We're looking at the paper: "JANUS: Agentic Cross-Language Fuzzing Harness Generation for Android Native Libraries".

Elias: Here's the gist of the paper. The gist The first agentic approach to synthesizing cross-language JNI-aware fuzzing harnesses for Android native libraries, yielding more valid harnesses and uncovering previously unknown vulnerabilities.

Nadia: Problem Statement Native libraries are pervasive in modern Android apps, invoked from Java/Kotlin through the Java Native Interface (JNI) for performance gains or to reuse battle-tested legacy code This cross-language interoperation, however, exposes the memory-safe Android Runtime to the unsafe C/C++ world, creating an attack surface that has been repeatedly exploited for full device compromise While fuzzing is a proven technique for vetting native libraries, state-of-the-art harness generation tools struggle to faithfully capture closed-source crosslanguage API usage (i) precise program analysis across the JNI boundary does not scale, whereas lightweight approximations miss critical invocation patterns; and (ii) none tackles the construction of complex composite objects consumed by JNI methods.

Elias: Root Challenges At the root of the predicament lie two fundamental challenges unique to harnessing Android native libraries.

Nadia: C1 Faithfully reconstructing cross-language invocation sequences requires intricate, app-specific runtime context (e.g., Java-side argument-object instantiation and field assignment, and native-side global state and runtime handles).

Title and authors: Nadia: So, we're looking at the paper "JANUS: Agentic Cross-Language Fuzzing Harness Generation for Android Native Libraries." This is about how to build better testing harnesses for those native libraries that live in Android apps.

Elias: Right, it’s tackling the problem where you have Java calling C++ through JNI, and the tools we have right now just don't work well because they can't figure out the full picture of what's happening across that language line.

Priya: I’m wondering what this means practically for us. We know these native libraries are a huge attack surface, and if we can generate better tests, we can find more vulnerabilities faster than before?

Nadia: Exactly. The paper suggests JANUS is the first agentic approach to synthesizing these harnesses, aiming to produce more valid ones and find bugs that were previously unknown.

Elias: The core idea is using an agentic workflow powered by Large Language Models, where these models act as autonomous agents doing code reasoning and planning instead of just being a simple helper in the fuzzing pipeline.

Priya: That sounds complicated. What exactly are these two main hurdles the paper is trying to overcome with this approach?

Nadia: The paper identifies two fundamental challenges at the root of why current tools struggle. First, reconstructing those cross-language invocation sequences requires a lot of app-specific runtime context, like knowing how a Java object gets instantiated and assigned fields to native code.

Elias: And second is the argument construction problem where JNI methods often take these complex composite objects whose construction logic you can't just guess from the JNI type signatures alone.

Priya: So, it’s not just about seeing a function signature; it’s about understanding how that object was actually built on the Java side before it even gets to native code?

Nadia: That’s right. C1 is faithfully reconstructing those invocation sequences needing that runtime context, and C2 is figuring out how to construct those complex arguments semantically.

Elias: The JANUS approach tackles this by having two main algorithms interact with the agentic workflows. One handles C1 by treating unmet dependencies as the driving force to resolve both explicit and implicit invocation contexts across Java instantiation and native state.

Priya: And for C2, how does that recursive decomposition idea actually work in practice? Can we really build complex objects from scratch using just primitive parts?

Elias: Yes, JANUS recursively decomposes those complex composite objects into synthesizable primitive objects and then reassembles them bottom-up to construct the exact objects expected by the native side.

Nadia: So, it’s not just guessing the structure; it’s building the structure from the ground up based on what the native code needs to receive.

Elias: The agentic design is where they get clever, equipping these LLM agents with a tool-augmented, structure-aware code retriever to stop them from wandering aimlessly through massive amounts of cross-language code.

Priya: That sounds like a necessary guardrail for the LLMs, because if you just throw all that cross-language code at it, it gets overwhelmed quickly.

Nadia: They also use a dedicated memory layer to keep track of verified intermediate artifacts across different methods, which helps tame context drift and reduces hallucinations during the long generation process.

The paper's summary: Nadia: So, JANUS is basically an agentic system that tries to write much better tests for those native libraries in Android apps.

Elias: Right, it uses these Large Language Models not just as a suggestion engine but as actual agents doing planning and reasoning to build the testing harness.

Priya: What I’m hearing is this agentic workflow is specifically designed to solve two major problems in cross-language fuzzing—the context of how the code runs and how complex data gets passed around.

Nadia: Exactly, it tackles reconstructing those invocation sequences, which is the hard part because you need to know what happened on the Java side and what state is active on the native side.

Elias: And then there’s this second problem where JNI methods take these complicated composite objects, and JANUS figures out how to build them correctly from scratch.

Priya: So, it’s moving beyond just looking at function signatures to actually modeling the entire application flow across the Java-native boundary.

Nadia: That's right. The paper says they treat unmet dependencies as the main driver, which helps them figure out those implicit calls you can't see just by reading the code.

Elias: And for building those complex arguments, they recursively break down those big objects into smaller pieces and put them back together piece by piece to match what the native side expects.

Priya: What’s interesting is their approach to keeping track of this long process—they use a memory layer to store verified steps so the agent doesn't completely lose track of what it's already done.

Nadia: That’s how they handle context drift, which is usually a killer when you have an agent making decisions over hundreds of steps.

Elias: The results show they produce significantly more valid harnesses and cover much more ground than the previous tools like Atlas++ or POIROT.

Priya: And the real kicker for me is that they found six previously unknown vulnerabilities in closed-source libraries from major Android vendors, which is a big deal for real-world security.

Nadia: Yeah, so this paper proposes this agentic method as a new way to approach fuzzing harnesses on the Java-native boundary.

Elias: It sets up a framework that resolves explicit and implicit calls and handles recursive argument construction using structure-aware retrieval tools.

Priya: It’s essentially saying we can build more robust tests if we let the AI agents handle the heavy lifting of figuring out those complex cross-language dependencies.

Nadia: Yeah, so this is laying some groundwork for how other auto-harnessing techniques could work across different language boundaries.

Elias: It’s definitely a step forward in how we automate testing for these kinds of security challenges.

Priya: It makes the idea that you don't need perfectly hand-crafted harnesses anymore if you have an agentic system to build them intelligently.

The paper's improvements: Tom: So, we're looking at how JANUS actually improved the original approach to building these fuzzing harnesses for Android native libraries.

Nadia: They focused on four specific enhancements to make it work better in practice and make sure the agents don't get lost.

Elias: I’m hearing they added a structure-aware code retriever, which is supposed to help the AI map Java declarations directly to the native functions so it doesn't have to guess the symbol space.

Priya: So, if you think of it as giving the AI a better map of where things are defined across both languages, making those initial mappings more reliable.

Nadia: Exactly, that retrieval layer is supposed to give the system a unified view between Java and native code definitions.

Elias: Then they have this dependency-driven call sequence extractor, which means instead of just trying random calls, it figures out what prerequisite calls are needed first before it can even try to hit the target function.

Priya: That’s a big deal for the execution validity because it ensures the harness is actually runnable and not just a collection of random function calls.

Nadia: And they have this recursive argument object construction, where they break down complex objects into simpler parts and reassemble them based on what the native side is actually reading.

Elias: That’s like taking a big LEGO structure and figuring out exactly which small blocks you need to build it correctly from the bottom up.

Priya: And they also added this validation-guided iterative refinement process, where they use compiler errors and runtime exceptions to tell the agent exactly which step went wrong so it can fix itself.

Nadia: That feedback loop closes the generation cycle, making sure every part of that massive synthesis effort is actually doing what it’s supposed to do.

Elias: The authors showed that disabling any one of these components caused a noticeable drop in quality, proving they all target different kinds of failure modes.

Priya: So, for someone just listening to the show, this means we move away from just hoping the AI writes something good and toward an AI that self-correcting based on how the code actually builds.

Nadia: It’s about making sure the synthesis isn't just syntactically correct but also semantically sound for execution.

Elias: The implication is that this agentic design could become a standard way to build complex cross-language test harnesses, not just something experimental.

Conclusion: Tom: So we’re wrapping up on JANUS, which is that agentic system for synthesizing JNI-aware fuzzing harnesses for Android native libraries.

Nadia: It's a lot of work to build those things right, and JANUS shows how an AI agent can actually handle the deep context needed for cross-language testing.

Elias: The main thing is that it takes something that used to require tons of brittle, hand-crafted heuristics and replaces it with a system that resolves call dependencies and builds complex objects recursively.

Priya: From my side, what’s compelling is the result—they found six real vulnerabilities in closed-source apps like those from Xiaomi and Samsung using this method.

Nadia: That means we're looking at a way to find holes in code that's completely inaccessible otherwise, which is a huge step for finding exploits cheaply.

Elias: It’s about moving the burden of context reconstruction from human researchers to an agentic workflow powered by LLMs that can self-reflect and iterate.

Priya: But we have to remember the paper flags its limitations—it’s still based on a linear execution model, so it might struggle with highly parallel or asynchronous native code interactions.

Nadia: True, it doesn't fully account for everything that happens in a massive Android app lifecycle, like Binder interactions or heavy concurrency issues.

Elias: So while the paper shows great promise for harness generation, we still need to figure out how to make that agentic planning robust enough for real-world asynchronous systems.

Priya: It certainly opens up a new way of thinking about automated testing, where the AI doesn't just run a script but builds the entire test environment intelligently.

Nadia: Yeah, it lays down a foundation for agentic cross-language fuzzing that we can use as a starting point for other types of security research.

Elias: It’s definitely interesting because it shows how LLMs can handle complex, multi-step reasoning tasks that are usually too tedious or impossible for a human to manage alone.

Nankai University · Zhongguancun Academy

cs.SE, cs.CR

Submitted: 2026-10-21

Updated: 2026-10-21

Comments: Harness Generation, Android Native Libraries, LLM Agent

Code: https://github.com/AtlasPlusPlus/Atlas-plusplus

License: http://creativecommons.org/licenses/by/4.0/

Importance score: 85/100

The gist: The gist The first agentic approach to synthesizing cross-language JNI-aware fuzzing harnesses for Android native libraries, yielding more valid harnesses and uncovering previously unknown

Key concepts

JNI Awareness
This means the fuzzing harness understands how Java code calls native C/C++ code via the Java Native Interface (JNI). JANUS specifically tracks these cross-language interactions to ensure the generated test cases correctly set up both the Java objects and the necessary native state required for a successful execution.
Agentic Workflow
JANUS uses Large Language Models (LLMs) as autonomous agents that perform reasoning, planning, and tool use. Instead of just analyzing code, these agents actively work together to synthesize complex harnesses by iteratively resolving dependencies and refining the generated test cases based on feedback.
Recursive Argument Construction
Native methods often take complex objects built from multiple parts. This concept describes how JANUS breaks down these large, composite objects into smaller primitive pieces, then reassembles them bottom-up to correctly construct the exact object structure expected by the native side of the JNI call.
Structure-Aware Code Retrieval
This tool helps JANUS understand the relationship between Java declarations and native implementations. It augments language servers with JNI method tables, allowing the system to create a unified map of symbols across both languages, preventing aimless exploration during harness synthesis.

Terminology

Summary

The gist The first agentic approach to synthesizing cross-language JNI-aware fuzzing harnesses for Android native libraries, yielding more valid harnesses and uncovering previously unknown vulnerabilities.

Problem Statement

Native libraries are pervasive in modern Android apps, invoked from Java/Kotlin through the Java Native Interface (JNI) for performance gains or to reuse battle-tested legacy code This cross-language interoperation, however, exposes the memory-safe Android Runtime to the unsafe C/C++ world, creating an attack surface that has been repeatedly exploited for full device compromise While fuzzing is a proven technique for vetting native libraries, state-of-the-art harness generation tools struggle to faithfully capture closed-source crosslanguage API usage (i) precise program analysis across the JNI boundary does not scale, whereas lightweight approximations miss critical invocation patterns; and (ii) none tackles the construction of complex composite objects consumed by JNI methods.

Root Challenges

At the root of the predicament lie two fundamental challenges unique to harnessing Android native libraries. C1 Faithfully reconstructing cross-language invocation sequences requires intricate, app-specific runtime context (e.g., Java-side argument-object instantiation and field assignment, and native-side global state and runtime handles). C2 Cross-language argument construction exposes a nontrivial semantic gap. JNI methods in real-world applications commonly accept complex objects (e.g., nested, user-defined composite types) whose construction logic cannot be inferred from JNI type signatures alone.

JANUS Approach

To overcome the inherent challenges above, JANUS, an agentic approach that synthesizes farreaching and meaningful cross-language JNI-aware harnesses, is proposed. JANUS’s key insights lie in two algorithms interacting with dedicated agentic workflows: To tackle C1, JANUS handles cross-language invocation sequences by treating unmet dependencies as the driving force, iteratively resolving both explicit and implicit cross-language invocation context, which spans Java-side object instantiation and native-side runtime state. To address C2, JANUS recursively decomposes complex composite objects into synthesizable primitive objects, then reassembles them bottom-up to construct the objects expected by the native side. JANUS implements core algorithms within an agentic workflow powered by Large Language Models (LLMs), capturing the JNI usage knowledge and semantic relationships between parameters, reducing reliance on brittle hand-crafted heuristics.

Agentic Design

JANUS builds an agentic workflow tailored for JNI-aware harness synthesis, in which the underlying LLMs act as autonomous agents that perform code reasoning, planning, tool invocation, and self-reflection throughout harness synthesis, rather than serving as auxiliary components in a conventional fuzzing pipeline. To sidestep the trap of overwhelming the LLM with sprawling cross-language code fragments and asking it to single out the critical pieces, JANUS equips the agent with a tool-augmented, structure-aware code retriever that forestalls aimless exploration. To tame context drift and hallucinations, JANUS persists verified intermediate artifacts across cross-language methods in a dedicated memory layer and closes the generation loop with a validation-guided iterative refinement that attributes failures to the responsible synthesis stage for targeted refinement.

Results and Contributions

JANUS produces 7.4×/5.9× more valid harnesses, and achieves 5.8×/6.5× the bitmap coverage compared to Atlas++ and POIROT, respectively. JANUS further uncovers 6 previously unknown memory-corruption vulnerabilities in closed-source native libraries shipped by mainstream Android vendors (e.g., Xiaomi, Vivo, Samsung). The paper makes three contributions: • We propose JANUS, the first agentic harness-synthesis approach toward JNI-aware fuzzing of Android native libraries, paving the way for broader auto-harnessing techniques across the Java-native boundary. • We present algorithms to guide agentic workflows for automated harness generation that resolve explicit and implicit call dependencies and recursively construct composite arguments, backed by structure-aware retrieval, validation-guided refinement, and harness memory. • JANUS outperforms the state of the art in harness synthesis, execution validity, and code coverage, and further uncovers 6 previously unknown vulnerabilities in closed-source native libraries shipped with mainstream Android vendor apps.

Evaluation

JANUS consistently outperforms both baselines across all metrics. It constructs 7,257 JNI-aware fuzzing harnesses (3.4× Atlas++, 5.7× POIROT) and successfully executes 6,094 of them (7.4× and 5.9×, respectively). In terms of fuzzing effectiveness, JANUS achieves a per-app mean bitmap coverage of 16.9% (vs. 2.9% for Atlas++ and 2.6% for POIROT). After deduplication, JANUS retains 5,390 crashes across 35 apps, compared to 404 (13 apps) and 905 (14 apps) for the two baselines.

Limitations

JANUS currently focuses on resolving explicit and implicit dependencies to reconstruct the JNI execution context, but is inherently based on a linear execution model. JANUS may fail to satisfy state dependencies established by asynchronous calls, and may miss concurrency-related vulnerabilities in highly parallelized native libraries. JANUS currently focuses on modeling the JNI call paths within the app itself, but does not account for deep interactions with the Android (e.g., Binder).

Conclusion

In this paper, we propose JANUS, the first agentic approach to synthesizing JNI-aware fuzzing harnesses for Android native libraries, yielding more valid harnesses and uncovering previously unknown vulnerabilities. Our work lays the foundation for agentic cross-language fuzzing harness generation in the Android ecosystem.

How it works

  1. Cross-Language Parser: This phase collects structural information for each defined class and method on the Java side, analyzes native libraries to extract function bodies along with implicit constraints they impose on incoming arguments, and resolves the runtime address of every native method on-device through the ART.

  2. Harness Synthesizer: This core stage comprises four components: Structure-Aware Code Retriever equips JANUS with cross-language code retrieval and comprehension capabilities, Dependency-Driven Call Sequence Extractor addresses how a JNI method should be invoked, producing JNI method cross-language call sequences, Recursive Argument Constructor then operates on these sequences to resolve how arguments should be constructed, producing argument construction schemes, and Harness Memory Manager persists verified intermediate artifacts across methods, alleviating the context pressure of long-horizon reasoning.

  3. Feedback-Driven Harness Refiner: JANUS constrains the generation space with a fixed JNI harness template that lays out the overall skeleton and the order in which each section is wired together, and closes the synthesis loop through feedback-driven repair.

Ablation Study

Disabling any component triggers a distinct regression, confirming that they target complementary failure modes rather than overlapping ones. For instance, Retriever underpins buildability by locating JNI entries and type definitions, causing the largest Build drop (−32.0%) and a substantial coverage drop (bitmap 16.9% → 10.5%). CallSeq bridges build and execution; without prerequisite calls, harnesses still build but crash due to uninitialized runtime state before reaching the target, collapsing the run/build ratio from 84.0% to 52.3%. RecArg governs exploration depth; freeform arguments are typically type-correct but semantically shallow, causing fuzzing to stall at native input-validation prologues. Memory sustains quality at scale; reuse is not required to get harnesses off the ground, making this variant the mildest (Build −8.9%, Run −16.5%).

Unknown Bug Discovery

JANUS produced 1,284 raw crashing inputs in total across all evaluated APKs. After manual triage, root-cause and reachability analyses confirm that these crashes correspond to 6 vulnerabilities, as shown in Table II. JANUS effectively discovers previously unknown vulnerabilities in real-world Android apps, confirming 6 vulnerabilities across 4 major vendors.

Cost Analysis

Averaged over three runs, each complete run of JANUS consumes 2.57 billion tokens at an input-to-output ratio of 11.05:1, with a context-cache hit rate of 94.7%. The total API cost per run is approximately ∼212 per runnable harness, demonstrating the economic practicality of JANUS.

Answer to RQ3

JANUS effectively discovers previously unknown vulnerabilities in real-world Android apps, confirming 6 vulnerabilities across 4 major vendors. The case study illustrates an out-of-bounds write in a native rendering library on Xiaomi flagship devices.

The paper demonstrates that JANUS effectively generates fuzzing harnesses for native libraries of Android apps.

Improvements for AI systems

  1. Agentic Harness Synthesis for JNI-aware Fuzzing: The improved system can synthesize cross-language JNI-aware fuzzing harnesses by iteratively resolving both explicit and implicit cross-language call dependencies to recover appspecific runtime context, and recursively assembles cross-language argument objects in a bottom-up manner.

  2. Structure Aware Code Retrieval: The system incorporates a structure aware retrieval layer that augments language servers with the JNI method table, allowing it to resolve mappings between Java declarations and native implementations to create a unified cross-language symbol space.

  3. Dependency Driven Call Sequence Extraction: The system employs a dependency driven algorithm where unmet dependencies are the driving force, iteratively resolving both explicit and implicit dependencies needed to reach the target JNI method. This allows it to reconstruct prerequisite call sequences that establish necessary execution context.

  4. Recursive Argument Object Construction: The improved system can recursively decompose complex composite objects into synthesizable primitive objects and reassemble them bottom-up, guided by a path selection mechanism that weighs how well each candidate covers the fields read on the native side.

  5. Validation Guided Iterative Refinement: The system closes the synthesis loop by constraining generation with a fixed JNI harness template and using feedback driven repair based on compiler diagnostics, runtime exceptions, and coverage feedback to attribute failures back to upstream stages for targeted refinement.

Abstract

Modern Android apps extensively rely on native libraries, bridging Java/Kotlin and C/C++ through the Java Native Interface (JNI). This cross-language interoperation, however, exposes the memory-safe Android Runtime to the unsafe C/C++ world, creating an attack surface that has been repeatedly exploited for full device compromise. While fuzzing is a proven technique for vetting native libraries, state-of-the-art harness generation tools struggle to faithfully capture closed-source cross-language API usage: (i) precise program analysis across the JNI boundary does not scale, whereas lightweight approximations miss critical invocation patterns; and (ii) none tackles the construction of complex composite objects consumed by JNI methods. In this paper, we propose JANUS, the first agentic approach to synthesizing cross-language JNI-aware fuzzing harnesses for Android native libraries. JANUS iteratively resolves both explicit and implicit cross-language call dependencies to recover app-specific runtime context, and recursively assembles cross-language argument objects in a bottom-up manner. JANUS leverages an autonomous agentic workflow to reduce reliance on hand-crafted heuristics, capturing the vast landscape of hidden API usage knowledge embedded in closed-source native libraries. Evaluation on 44 popular real-world apps (such as Google and YouTube Music, covering 21,386 JNI methods total) shows that JANUS produces over 5.9 times as many valid harnesses (6,094) as state-of-the-art automatic harnessing tools. On pre-installed apps from five mainstream Android vendors (e.g., Xiaomi, Vivo, Samsung), JANUS further uncovers 6 previously unknown vulnerabilities in closed-source native libraries.

Sources

Related papers