TL;DR: Some issues hidden for more than 15 years were among 105 vulnerabilities validated across 34 Ruby projects, with the affected packages exceeding 8.6 billion downloads, underscoring how native extensions can turn a seemingly memory-safe ecosystem into an application compromise path, according to depthfirst. The governance lesson is that software supply chain risk now includes reachability, lifetime management, and downstream exposure, not just version tracking, per depthfirst's research.
At a glance
What this is: depthfirst analysed the Ruby ecosystem and found more than 100 validated memory-safety and lifetime-management flaws across 34 projects, with some defects lingering for over 15 years and affecting widely downloaded packages.
Why it matters: For IAM, NHI, and broader software supply chain governance, the lesson is that downstream reachability and runtime exposure matter as much as dependency versioning when risky code sits inside native extensions.
Context
Ruby is often treated as memory safe at the language level, but that assumption breaks once code crosses into native extensions and lower-level C bindings. In that boundary layer, object lifetime, bounds checking, and garbage-collector visibility become security controls, not implementation details.
This article is really about software supply chain governance, not Ruby alone. The identity angle is indirect but real: if downstream applications embed vulnerable dependencies, the operational question becomes which software components are effectively trusted to act on behalf of the application and for how long.
The findings are typical of a wider open-source risk pattern. The ecosystem may look stable from the outside while hidden flaws persist deep inside commonly used packages for years.
Key questions
Q: What fails when a Ruby gem uses native code outside the language runtime's memory guarantees?
A: The failure mode is usually at the boundary between managed Ruby objects and unmanaged C state. Once the extension narrows types, stores hidden references, or reuses stale pointers, ordinary runtime protections no longer apply. That is why memory-safety bugs in gems can become out-of-bounds reads, use-after-free conditions, or process crashes even when the surrounding Ruby code looks safe.
Q: Why do reachable dependency findings matter more than raw vulnerability counts?
A: Reachability matters because a dependency flaw only creates immediate risk if the vulnerable code path is actually used by the application. Counting every disclosed CVE without that context inflates noise and wastes remediation time. Teams get better risk decisions when scanning shows whether code can invoke the vulnerable functionality, not just whether the package contains it.
Q: What are the signs that a gem's native extension may be unsafe in production?
A: Look for extensions that convert values between different integer sizes, cache Ruby objects inside C structures, or rely on packed state to represent several conditions at once. Those patterns often produce the bugs seen in this research: bad bounds checks, stale references, and corrupted control flags. Any extension that handles untrusted input deserves extra scrutiny.
Q: How should security teams respond when an exploited dependency sits in a downstream application?
A: Treat it as an application risk, not a package inventory issue. Identify every deployed service that reaches the vulnerable code, confirm whether the affected path is callable with real inputs, and prioritise fixes by exploitability and exposure. The goal is to remove reachable risk first, then complete the broader dependency cleanup.
Technical breakdown
Why native extensions break the memory-safety assumption
Ruby code itself benefits from managed memory, but native C extensions do not inherit the same protections. Once a gem crosses that boundary, the security model depends on manual bounds checks, explicit lifetime handling, and correct interaction with the garbage collector. That creates a different class of defect from ordinary Ruby bugs: out-of-bounds reads, use-after-free conditions, and stale references that can survive long after code review would normally focus elsewhere. In practice, the risky area is not the language surface but the translation layer where Ruby objects are mapped into C data structures.
Practical implication: Treat native extensions as a separate review domain and not as ordinary Ruby code.
How a type or lifetime mismatch becomes exploitable
The article shows three recurring failure modes. First, a value can be validated in one type but used in another, which breaks the check and lets out-of-bounds access slip through. Second, a Ruby object can be retained in native state without being visible to the garbage collector, creating a stale reference that can later be reused after free. Third, identity state can be compressed into a single integer until one flag spills into another and changes lock semantics. Each bug is small locally, but each changes what the runtime believes is still safe to use.
Practical implication: Review extension code for type narrowing, hidden references, and packed state before release.
Why reachability matters more than package presence
A vulnerable gem is only exploitable in practice when a downstream application actually reaches the affected code path. That is why static version lists are not enough. Security teams need evidence of call paths, runtime exposure, and whether the vulnerable function is reachable in the deployed application. The article’s GitLab example is important because it shows how a flaw in a gem can be chained into application compromise once the vulnerable code is exercised. This is a supply chain problem at the execution layer, not just the dependency layer.
Practical implication: Prioritise reachable vulnerable code paths over generic dependency inventory alone.
Threat narrative
Attacker objective: The attacker aims to turn a dependency-level flaw into application compromise, process control, or a reliable crash path in software that trusts the affected gem.
- Entry occurs when an application imports a Ruby gem with a native extension that contains a hidden memory-safety flaw.
- Credentialless escalation is replaced here by runtime abuse, where the attacker triggers malformed input or a crafted code path to force the vulnerable C routine into unsafe memory access.
- Impact follows when the flaw produces out-of-bounds reads, stale object reuse, or lock-state corruption that can crash the process or support remote code execution in downstream applications.
Breaches seen in the wild
- ASP.NET machine key attacks 2025: Developers copied ASP.NET machine keys from public sources; attackers used one to run Godzilla via ViewState. Microsoft found 3,000+ such keys.
- Sisense breach 2024: A credential in Sisense's GitLab reportedly opened S3 buckets of customer tokens, passwords and certificates; CISA urged a full reset.
Read and download The State of NHI & AI Agent Breach Report 2026, covering 200+ breaches impacting Non-Human Identities including AI Agents.
NHI Mgmt Group analysis
Hidden supply chain risk now includes runtime trust, not just version trust: the key problem in this article is not that Ruby dependencies exist, but that native extensions quietly expand the trusted computing base beyond what many teams govern. When the runtime boundary between Ruby and C is involved, package inventory alone does not answer whether the code is actually safe to execute. Practitioners need to govern reachability and execution path, not just dependency presence.
Memory-safe language branding creates a false sense of containment: Ruby may reduce whole classes of memory bugs, but the article shows that the protection ends where native extensions begin. That is a governance blind spot because teams often assume the language choice lowers the review burden across the whole ecosystem. The right lesson is that memory-safety assumptions must be validated at the extension boundary, especially for packages that handle untrusted input.
Object lifetime is a security control, not an implementation detail: several of the validated flaws came down to whether the runtime could still see an object that native code planned to reuse later. That is the same kind of governance failure seen in broader identity and access systems when ownership and revocation are not explicit. For practitioners, lifecycle visibility should be treated as part of supply chain assurance, especially in dependencies that cache references or state across calls.
Reachable flaws deserve higher priority than abstract vulnerability counts: 105 vulnerabilities across 34 projects sounds broad, but the more important question is which ones downstream applications can actually hit. The article’s GitLab chain shows why exploitability depends on context, not just CVE-style tallies. Security teams should focus remediation on reachable, high-impact code paths first, because that is where dependency risk turns into operational compromise.
What this signals
Reachable dependency risk is the real supply chain problem: teams do not need another generic inventory of packages, they need to know which dependencies can actually be exercised by production traffic. That means analysis has to move from version posture to execution posture, because a dormant flaw and a callable flaw are not the same risk.
Native extension governance should sit beside dependency management: the article makes clear that language-level safety does not extend automatically into unmanaged code. For practitioners, that means extension review, lifetime handling, and garbage-collector visibility belong in the same control conversation as patching and SBOM maintenance.
For practitioners
- Audit native extensions separately Review every gem that ships C extensions as its own risk class, with manual attention on bounds checks, type conversion, and object lifetime handling.
- Prioritise reachable vulnerable paths Map which vulnerable gem functions are actually invoked in production so remediation decisions can be based on exploitability, not package presence alone.
- Validate garbage-collector visibility Check that native code keeps every live Ruby object visible to the garbage collector for as long as the extension may use it.
- Track downstream exposure continuously Maintain a dependency-to-application map so fixed releases can be rolled out quickly when a vulnerable gem is confirmed in use.
Key takeaways
- Ruby's managed runtime does not eliminate supply chain risk once gems rely on native extensions and unmanaged memory handling.
- The validated flaws in this research show that reachability and runtime exposure matter more than simple dependency counts.
- Security teams should prioritise the code paths an application can actually invoke, because that is where vulnerable gems become compromise paths.
Standards & Framework Alignment
This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.
MITRE ATT&CK addresses the attack and risk surface, while NIST CSF 2.0, CIS Controls v8 and SLSA set the governance and control requirements practitioners need to meet.
| Framework | Control / Reference | Relevance |
|---|---|---|
| MITRE ATT&CK | TA0006; TA0008 — Credential Access; Lateral Movement | Reachable gem flaws can be chained from initial code execution into broader application compromise. |
| Recommendation — Map vulnerable dependency paths to TA0006 and TA0008 so you can hunt for reachable exploitation routes in production. | ||
| NIST CSF 2.0 | PR.DS-01 — Data-at-Rest Protection | The article centres on data and code integrity risks created by unsafe dependency behaviour. |
| Recommendation — Use PR.DS-01 to limit downstream exposure when dependency flaws can expose or corrupt application data. | ||
| CIS Controls v8 | CIS-16 — Application Software Security | The research is about insecure third-party code embedded in application dependencies. |
| Recommendation — Apply CIS-16 to review third-party libraries, test unsafe code paths, and remediate vulnerable extensions. | ||
| SLSA | L3 — Build integrity | The article highlights software supply chain trust and the need to know what reaches production. |
| Recommendation — Adopt SLSA-aligned provenance checks so dependent artifacts can be traced and verified before deployment. | ||
Key terms
- Native Extension: A native extension is code written in a lower-level language such as C that a higher-level runtime loads to extend functionality. It can improve performance or add capabilities, but it also bypasses some managed-runtime safety guarantees and must handle memory, bounds, and object lifetimes correctly.
- Reachable Vulnerability: A reachable vulnerability is a weakness that is present in code or a dependency and can actually be exercised in the deployed environment. This distinction matters because many findings are theoretical, while reachable issues represent real attack paths that deserve higher priority, faster remediation, and stronger policy enforcement.
- Use-after-free: A use-after-free occurs when code continues to read or write memory after it has already been released. In kernel networking paths, this often becomes a security issue because stale pointers can expose secrets, corrupt control flow, or crash the system under the right timing conditions.
- Object Lifetime Management: Object lifetime management is the control of how long data remains valid while software is still using it. In mixed-runtime systems, the challenge is making sure native code and the garbage collector agree on what is still live. Weak lifetime handling is a common source of security flaws.
Deepen your knowledge
The NHI Foundation Level course, the industry's only accredited NHI security programme, covers NHI governance, secrets management, and workload identity. It helps practitioners connect identity controls to the wider security programmes they already run.
Published by the NHIMG editorial team on August 21, 2026.
Updated on October 12, 2026.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org