Java, Wasm and BPF demonstrate that it is possible to have statically-verifiable bytecode for JIT-compiled languages. Lua’s problem is that the bytecode doesn’t provide the information necessary to fully verify its safety.
All of those formats are designed to be translated to machine code when maximum performance is desired. Whereas Lua byte code is designed and optimized to be interpreted directly.
One step in Lua's evolution was to change from a stack machine to a register machine: https://www.lua.org/doc/jucs05.pdf This made the interpreter faster, but also (I suspect) more difficult to verify. I believe both Java and Wasm are stack machines (don't know about BPF).
Technically speaking, CIL is always compiled by CoreCLR (it has interpreter internally but it is never used and therefore has succumbed to bitrot), it is sometimes interpreted by Mono on certain platforms as a stand in for dynamically emitted code. A special case used to be with WASM target with Mono but supposedly that's in the past.