Look for request handlers that accept base64 blobs, YAML payloads, or JSON objects and immediately feed them into Marshal.load, YAML.unsafe_load, or Oj.load. Also watch for code that reads method names from parameters and forwards them into send or public_send. These patterns often appear in convenience code that crosses trust boundaries without validation.
How to spot unsafe deserialisation and reflective invocation in Ruby
Misuse usually shows up where untrusted input is turned into executable structure, then consumed with little or no validation. In Ruby, that often means deserialisers that can revive objects or invoke code paths, and reflective calls that let a request choose the method name. The danger is not the syntax itself, but crossing a trust boundary without constraining what the input may become.
Watch for handlers that treat request bodies as convenience data formats rather than attacker-controlled input. Base64 blobs, YAML documents, and JSON objects become suspicious when they are passed straight into Marshal.load, YAML.unsafe_load, or Oj.load with no schema check, type check, or allowlist. That pattern is especially risky when the code assumes the payload is “just data” but the parser can materialise richer objects or trigger side effects during object construction.
Reflection has a similar smell when method choice comes from the user rather than from fixed application logic. Code that reads a method name from parameters and forwards it into send or public_send can become dangerous if the input is broad enough to reach unintended methods. The key question is whether the application is constraining the callable surface to a small, explicit set, or whether it is effectively letting the requester choose behaviour inside the process.
What makes these patterns exploitable
Unsafe deserialisation becomes serious when the runtime or library can instantiate objects that do more than hold fields. If deserialised content can influence class selection, callbacks, or object state, the input may move from passive data to active behaviour. That is why the same pattern can range from harmless convenience to remote code execution depending on the parser, the data format, and what classes are reachable in the process.
Reflection is exploitable when the method dispatch boundary is too wide. A benign use of public_send with a fixed allowlist is very different from accepting arbitrary method names from a query parameter, then invoking them against a rich object. The latter can expose administrative paths, bypass intended workflows, or reach helper methods that were never meant to be remotely callable.
For appsec readers, the most relevant reference point is OWASP ASVS, because it frames these issues as input validation, secure API behaviour, and control over sensitive execution paths. It is also useful to compare the pattern against the broader OWASP Top 10 view of injection-style flaws and unsafe trust in external input.
Code and review signals that deserve immediate attention
During review, treat the following as strong indicators of a likely issue:
- Controller or job code that accepts encoded blobs and immediately hands them to a deserialiser.
- YAML, Marshal, or Oj calls that occur before authentication, authorization, or any allowlist check.
- Method dispatch driven by request parameters, especially when the target object has many public helper methods.
- Convenience abstractions that hide the boundary, such as “hydrate”, “import”, “execute”, or “invoke” wrappers that do not document accepted types.
- Exception handling that catches parser errors but still continues with partially trusted objects.
These signals matter because they tell you the application is making a trust decision based on attacker-controlled syntax. If the code path can reach privileged logic, sensitive state changes, or dynamic execution, then the bug is no longer theoretical, it is a realistic RCE or privilege-abuse candidate.
Risk and Threat Considerations
Unsafe deserialisation and unconstrained reflection create a direct path from input handling to code execution or sensitive method invocation. The risk is highest when the payload crosses a trust boundary before validation, because the application may parse attacker-supplied structure or call attacker-influenced methods inside a privileged process.
Failure mechanism: A parser or reflective dispatcher accepts untrusted input as if it were trusted application data, then materialises objects or invokes methods that were never intended to be remotely selected.
Impact: The result can be remote code execution, denial of service, unauthorized state changes, or exposure of helper methods and internal application logic that should not be reachable from a request.
Standards & Framework Alignment
This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.
OWASP API Security Top 10 and MITRE ATT&CK address the attack and risk surface, while OWASP ASVS sets the governance and control requirements practitioners need to meet.
| Framework | Control / Reference | Relevance |
|---|---|---|
| OWASP ASVS | V2 — Validation and Business Logic | Unsafe input reaches parser and dispatch logic here. |
| V15 — Secure Coding and Architecture | The issue is insecure trust-boundary design in application code. | |
| V16 — Security Logging and Error Handling | Parser and dispatch failures should be observable and safely handled. | |
| Recommendation — Validate input types and constrain business logic before deserialising or dispatching methods. Design explicit trust boundaries and remove attacker-controlled dynamic execution paths. Log parsing and dispatch anomalies and fail closed on unexpected input. | ||
| OWASP API Security Top 10 | API5 — Broken Function Level Authorization | User-chosen method dispatch can expose unintended callable functions. |
| API8 — Security Misconfiguration | Unsafe loaders and permissive reflection are common hardening failures. | |
| Recommendation — Restrict callable API functions to an explicit allowlist. Harden deserialisation and reflection defaults before exposing the API. | ||
| MITRE ATT&CK | T1210 — Exploitation of Remote Services | A reachable parser or dispatcher can be abused to gain code execution remotely. |
| Recommendation — Hunt for remotely reachable parsing and dispatch chains that enable exploitation. | ||
Practitioner Guidance
What to prioritise: Trace every path from request data to deserialiser or reflective call, then classify the input as untrusted unless it is explicitly constrained by a narrow allowlist. A fixed method map is safer than free-form dispatch, and simple type validation is safer than assuming a blob is harmless because it arrived as YAML, JSON, or Base64.
What to verify: Confirm that the application never deserialises data from the network with a parser that can instantiate arbitrary classes or revive rich objects unless the format is fully controlled. For reflection, verify that only a small, explicit set of method names can be reached, and that no security-sensitive helper methods sit on the same object surface.
Practitioner takeaway: Treat deserialisation and reflection as execution boundaries, not convenience features, and require explicit constraining logic before either one can be influenced by a request.
Related resources from NHI Mgmt Group
- What are the signs that an application is misusing external APIs in a way that creates security exposure?
- What are the signs that reflection is being misapplied in an application?
- What are the signs that a simple RBAC approach is starting to fail in a Ruby application?
- What are the signs that a Ruby application is vulnerable to command injection?
Deepen Your Knowledge
Reviewed and updated by the NHIMG editorial team on September 29, 2026.
NHI Mgmt Group — the #1 independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org