Ruby Workers Face Critical RCE from Unsafe Oj Deserialization
NullSecurityX disclosed deterministic RCE in Ruby background workers using Oj.load deserialization. Unauthenticated attackers craft JSON payloads triggering arbitrary shell commands via Node class. No gadget chains required; single line data = Oj.load(job.payload) enables full compromise.
Applications store user-controlled JSON in job queues for async processing. Background workers deserialize payloads reconstructing executable Ruby objects. Oj gem object mode bridges data-to-code boundary silently.
{“^o”:”Node”} JSON directive instantiates Node class with injected methods. Capability-based dispatch calls run_find exposing Open3.capture3 execution. Shell commands pass as find arguments achieving RCE.
Attack chain spans web request to worker execution without authentication. Dynamic respond_to? routing authorizes malicious objects automatically. Design flaw assumes deserialized data remains inert.
find / -maxdepth 0 -exec sh -c ‘command’ pattern executes payloads reliably. No memory corruption or obscure conditions needed. Worker context grants filesystem, network, persistence access immediately.
Enterprise Ruby deployments face highest exposure from SaaS patterns. Sidekiq, Resque, GoodJobs patterns require immediate audits. Deserialization represents persistent blindspot in modern web architectures.

Vulnerability Mechanics Table
| Component | Risk | Attack Vector |
|---|---|---|
| Oj.load | Critical | Object reconstruction |
| Node.run_find | Critical | Open3.capture3 abuse |
| respond_to? dispatch | High | Unauthorized method calls |
| Job payload storage | High | User-controlled JSON |
Attack Indicators
| Type | Indicator |
|---|---|
| JSON Pattern | {“^o”:”Node”} object tag |
| Process Execution | find / -maxdepth 0 -exec sh |
| Worker Context | Open3.capture3 from jobs |
| Suspicious Methods | Dynamic dispatch calls |
Oj.safe_load enforces strict parsing blocking object creation. Explicit job handlers replace dynamic dispatch entirely.
Remediation Steps
- Replace Oj.load with Oj.safe_load everywhere
- Implement explicit job class mapping
- Remove Open3.capture3 from deserialized contexts
- Audit all background worker payloads
- Deploy WAF rules blocking ^o JSON patterns
- Monitor find command abuse from workers
Production Rails, Sinatra apps require comprehensive deserialization scans. Container escapes possible from compromised workers. Rapid patching prevents widespread exploitation campaigns.
FAQ
Oj.load deserializing untrusted JSON payloads containing {“^o”:”Node”}.
Oj gem object mode reconstructing executable Ruby objects.
Unauthenticated JSON payload storage in background job queue.
Node.run_find method abusing Open3.capture3 shell calls.
Switch to Oj.safe_load strict parsing mode.
Sidekiq, Resque, GoodJobs, custom implementations.
Read our disclosure page to find out how can you help VPNCentral sustain the editorial team Read more
User forum
0 messages