JGD (JavaGadgetDigger): an autonomous agent for Java deserialization gadget chains
JavaGadgetDigger is an autonomous agent for Java deserialization research. Point it at a JAR directory and it produces gadget chains and weaponized proof-of-concept payloads, with no intermediate user input.
Why the last mile matters
For most Java deserialization work, the hard part is the last mile: you have the classpath in front of you, and you need a working chain from an entry point to a dangerous sink. JGD automates that step end to end.
What it produces
-
Known public chains with a four-state determination:
PRESENT/VERSION/ASSEMBLE/FIRE. - Novel, unpublished chains discovered through static + dynamic analysis with adversarial LLM auditing.
- Weaponized PoCs - serialized payloads with an RCE-closure demo (benign marker file).
All decisions are internalized: JARs in, chains out.
Pipeline
Input: any JAR directory Output: chains + PoCs
Known --> Bridge --> Chain --> PoC
Chains Discovery Pairing Weapon
| | | |
signature bytecode dynamic benign
+ version + CHA graph contract payload
gates + dispatch synthesis + fire
edges + 5 carriers test
Discovered chains
T1 - novel entry
| Chain | Bridge class | Carrier | JDK |
|---|---|---|---|
objlongpair-hashmap |
org.apache.activemq.artemis.api.core.ObjLongPair |
HashMap rehash | 17+ |
T2 - new bridge classes
Vavr family (7 chains):
| Chain | Bridge class | Carrier | JDK |
|---|---|---|---|
tuple1-8-hashmap |
io.vavr.Tuple1 ... Tuple8
|
HashMap rehash | 11 |
either$left-hashmap |
io.vavr.control.Either$Left |
HashMap rehash | 11 |
either$right-hashmap |
io.vavr.control.Either$Right |
HashMap rehash | 11 |
option$some-hashmap |
io.vavr.control.Option$Some |
HashMap rehash | 11 |
validation$valid-hashmap |
io.vavr.control.Validation$Valid |
HashMap rehash | 11 |
validation$invalid-hashmap |
io.vavr.control.Validation$Invalid |
HashMap rehash | 11 |
hasharraymappedtrie$leafsingleton |
io.vavr.HashArrayMappedTrie$LeafSingleton |
HashMap rehash | 11 |
Spring AOP family (6 chains): composablepointcut-hashmap, methodmatchers$unionmethodmatcher, methodmatchers$intersectionmethodmatcher, singletontargetsource-bave, hotswappabletargetsource-bave, defaultintroductionadvisor-bave.
Guava family (3 chains): functions$formapwithdefault, predicates$isequaltopredicate, present.
Other libraries: mutableobj-bave (hutool-core), antlr4-pair-bave (antlr4-runtime), clojure-proxy-hashmap (clojure), jacksoninject$value-bave (jackson-annotations), objectidgenerator$idkey-bave (jackson-databind), tolerantmap-hashmap (snakeyaml), scala-objectref-bave (scala-library).
T3 - variants
ewah-hashmap (JavaEWAH, used by Lucene/Elasticsearch) and the federation*-hashmap family (4 chains, Artemis).
Example dispatch stack (ObjLongPair, T1, JDK 17)
HashMap.put -> HashMap.hash
-> ObjLongPair.hashCode(ObjLongPair.java:55)
-> Objects.hash -> Arrays.hashCode
-> EqualsBean.hashCode -> EqualsBean.beanHashCode
-> ObjectBean.toString -> ToStringBean.toString -> Method.invoke
-> TemplatesImpl.defineClass -> payload static block
Quick start
CLI mode (batch audit)
# Install deps (Python 3.10+, JDK 11 and 17, ECJ compiler)
pip install chromadb # optional, for RAG persistence
# Point at any JAR directory, get chains + PoCs
python3 audit_target.py --target /path/to/jars --name "your-product"
TUI mode (interactive)
python3 tui.py # English
python3 tui.py --lang zh # Chinese
Key bindings: arrow keys or j/k to navigate chains, Enter to toggle detail, t to switch language, q to quit.
Project structure
jgd/
audit_target.py # Product CLI entry point
tui.py # Interactive TUI
jgd/ # Core agent modules (25)
verify_agent.py # Bridge discovery + ds adversarial audit (incremental checkpoint)
chain_complete.py # Chain pairing + exhaustion proof (per-item evidence)
poc_gen.py # Weaponized PoC generation (heq/jackson/map-dispatch tails)
known_chains.py # Public chain four-state determination (155-chain SQLite)
build_chain_db.py # Chain DB builder (155 chains, 168 version gates)
novel_chains.py # Novel chain auto-tiering (GLM propose + DS verify)
matrix_agent.py # Multi-JDK probe orchestration
bcdisasm.py # Pure-Python bytecode disassembler
bridge_fix.py # Operand-stack symbolic execution
chroma_store.py # RAG with corpus-scoped collections
llm.py # Dual-model (GLM + DeepSeek)
scope.py # Corpus fingerprint isolation
conductor.py # Acceptance-gated terminal verdict
...
examples/chains.json # All discovered chains (machine-readable)
examples/chains.md # Human-readable chain catalog
tests/test_smoke.py # Third-party reproducible test suite
ARCHITECTURE.md # 25-module graph + design decisions
CHANGELOG.md # Design decision history (R6-R52)
How it works
1. Public chain determination. A 155-chain SQLite database with per-chain family, source, CVE, trigger method, sink type, JDK range, conditions, and jar version gates. Class signature matching (jar-scoped) plus JDK internal class detection, with per-jar multi-version verdicts (APPLICABLE / BLOCKED / UNVERIFIED) and dynamic assembly + fire verification using the target's own JARs.
2. Novel chain discovery. Static operand-stack symbolic execution detects receiver-bridges, argument-bridges, and Map-dispatch bridges. A real-time corpus-fingerprinted call graph plus CHA dispatch edges and JDK builtin sink seeds. Dynamic batch-parallel JVM probes across 5 carriers, with field-contract synthesis and multi-JDK coverage. Observability via marker reachability, exception stack frames, marker caller-stack, and MAPDISPATCH signals.
3. Adversarial auditing. Dual-model proposal/verification (GLM proposes, DeepSeek verifies) with incremental checkpointing, so verify / chain / poc all resume on the same fingerprint.
Top comments (0)