LoadGuard#owner_name resolved the receiver with `receiver.is_a?(Module) ? receiver : receiver.class`. The receiver is the gadget. A method-erased proxy answers .class and .is_a? through method_missing, and method_missing is exactly what the shipped erb-def-module chain enters through, so identifying the object fired the chain it was about to veto. TracePoint does not trace a handler's own nested calls, so that detonation was invisible to the guard as well as unguarded by it. The observable result was a guard reporting a block on a payload that had already written its canary: strict guard: blocked -> deserialization hook (class with no name)#method_missing canary created? true "(class with no name)" was the tell: receiver.class had been answered by method_missing, which returned the anonymous Module that ERB#def_module builds. Resolve identity through Object#class, Object#is_a? and Module#name unbound and bind_call'd onto the receiver, so nothing dispatches to it. Both hook sets now veto with the canary absent and the real owner named. Side effect, and it is the stronger behaviour: Module#name read unbound means a class that overrides .name to raise is now named truthfully instead of reported anonymous. test_an_owner_that_refuses_to_name_itself_fails_closed asserted the old outcome and is rewritten to assert the new invariant. test_the_guard_never_dispatches_a_method_on_the_receiver_it_inspects pins it, and it isolates: instrumenting a wiped proxy shows [] against the fix and [:is_a?, :class] against the revert. |
||
|---|---|---|
| .. | ||
| base64-tool | ||
| c2-beacon | ||
| caesar-cipher | ||
| canary-token-generator | ||
| deserialization-gadget-lab | ||
| dns-lookup | ||
| firewall-rule-engine | ||
| hash-cracker | ||
| keylogger | ||
| linux-cis-hardening-auditor | ||
| linux-ebpf-security-tracer | ||
| metadata-scrubber-tool | ||
| network-traffic-analyzer | ||
| simple-port-scanner | ||
| simple-vulnerability-scanner | ||
| steganography-multi-tool | ||
| systemd-persistence-scanner | ||