A deep technical dive into how JGDMS (an Apache River/Jini fork) with the DirtyChai security extension carries user identity chains across remote calls on the JVM. Covers the 0x02 wire format for marshalling Subject chains, strict receiver-side limits against DoS, a fixed allowlist of trusted principal classes (never instantiating remote-supplied class names), JWT verification caveats (default verifier only checks exp/iat, not signatures), reflective tricks needed to keep code compiling on stock OpenJDK where UserSubject doesn't exist, propagating identity across thread boundaries with SubjectAwareExecutor, and unanimous permission checks across all participants in a distributed transaction via TxnManagerImpl.
Questions this post answers
How does BasicInvocationDispatcher in JGDMS prevent a hostile peer from causing an OutOfMemoryError with fake Subject counts?
BasicInvocationDispatcher enforces hard limits on the receiving end regardless of what a writer claims in the 16-bit and 8-bit count fields: at most 16 Subjects, 64 principals per Subject, 4 tokens per Subject, and 65,536 bytes per token. Exceeding any limit fails the request with an IOException, preventing unbounded allocation from a malicious count value. Developers hardening RPC wire formats against DoS can track deserialization limits and protocol changes on daily.dev.
Why does Subject.current() not fall back to reading a user Subject from AccessControlContext in this JGDMS security model?
Subject.current() returns only the first Subject bound via callAs and nothing else; no user Subject hides in the AccessControlContext as a fallback. The getSubject(acc) method is a deprecated shim that ignores its argument and simply calls current(). Code needing the full delegation chain must use the ClientUserSubject accessors explicitly. Engineers debugging identity propagation quirks like this follow deep JVM security explainers on daily.dev.
Why does a virtual thread submitted to a plain ExecutorService lose the caller's Subject identity in Java?
A ScopedValue binding does not cross into a thread you spawn, so a virtual thread started inside a service method inherits the server's worker identity from the AccessControlContext instead of the caller's user identity, silently, with no exception or warning. SubjectAwareExecutor wraps any executor to capture the Subject array and SecurityContext at submission time and re-establish them on the worker thread. Teams wiring identity through virtual threads can keep up with JVM concurrency nuances on daily.dev.