Scripting languages are an essential part of many software environments. Common languages like Python, Ruby, or PHP power large parts of the modern web but bugs in their runtime environments allow attackers to break memory safety and sandboxing guarantees. A common bug class is callback bugs which happen when user-defined callbacks violate runtime invariants. For example, an object may be freed that is still in active use. These issues result in use-after-free, null pointer dereferences or type confusion.
Example of clearing a list while iterating through it:
class poc():
def __eq__(self, other):
l.clear()
return NotImplemented
l = [poc(), poc()]
3 in l
The check on the last line triggers a use-after-free as the l.clear() removed the elements in the array during the equal check. Such interactions between native implementations and user defined callbacks result in violations of the language level guarantees.
Triggering a callback bug requires a set of four preconditions that are satisfied: (i) control flow must reach a callback in the script, (ii) the callback must involve an attacker-controlled object, (iii) the callback must introduce unintended side effects such as freeing memory, and (iv) the native code must be unaware of the memory operation and then mishandles the affected object after the callback returns.

Our goal in this research is to establish a link between the script-side callbacks and their native-side invokers and to discover such bugs automatically. In CrossFit, we combine static analysis (to find interesting locations and patterns) with targeted fuzzing to trigger these bugs. CrossFit generates PoC scripts with custom classes and magic methods to demonstrate these vulnerabilities.
The key idea behind CrossFit is that we leverage context link analysis to bridge the gap between the script side and the runtime side. As these are different programming languages and contexts with different guarantees, we have to keep state at these different levels of abstraction. For each scripting language, we identify these callback invokers among their public API and then build our analysis on the LLVM IR level to handle the low level implementations transparently. Using this collected information, CrossFit then generates targeted scripts with PoC inputs to test the four conditions of callback bugs. This allows us to bias the generation towards scripts that are more likely to trigger interesting bugs.
In our evaluation on PHP, Python, and Ruby we discovered 21 new bugs and demonstrated that our targeted PoC generation can cover callback code and cross-language interactions more deeply. The full details are in the CrossFit paper and the source code are of course available.
This work is published at FSE'26 and thhe main credit of this work goes to Chibin Zhang who worked on the abstractions, refinement of the bug pattern, and design of the PoC generator.