Runtime and dependency security policy
This policy explains what Otto's Ruby and gem version declarations guarantee, what they do not guarantee, and what applications using Otto must do to keep a deployed bundle patched.
Ruby compatibility and security maintenance
Otto separates runtime compatibility from interpreter security maintenance. A blocking compatibility target must pass Otto's test suite; provisional targets are exercised without blocking releases. Only the Ruby project can provide security maintenance for the interpreter.
| Ruby version | Otto compatibility policy | CI status |
|---|---|---|
| 3.2 | Retained as a compatibility target for now, despite upstream end of life | Blocking, with locked and freshly resolved dependencies |
| 3.3–3.4 | Supported compatibility targets | Blocking, with locked and freshly resolved dependencies |
| 3.5–4.0 | Accepted by the gem's Ruby version range, but compatibility remains provisional | Experimental and non-blocking, with locked and freshly resolved dependencies |
Ruby 3.2 reached upstream end of life on April 1, 2026. It receives no interpreter security maintenance. Otto's continued compatibility testing cannot correct vulnerabilities in Ruby 3.2 itself. Applications with a security maintenance requirement should run Otto on a Ruby version that the Ruby project currently maintains. Check the Ruby branch maintenance status when selecting a runtime.
The required_ruby_version range in otto.gemspec controls whether RubyGems
may install Otto. It does not mean every version in that range has the same CI
or upstream security status. The table above is the support policy for the
current matrix.
What dependency ranges mean
The runtime dependency ranges in otto.gemspec express the versions Otto
expects to be API-compatible with. Their lower bounds are compatibility
baselines, not a promise that every allowed version is free of known
vulnerabilities or still receives security fixes.
Otto may exclude a known-bad dependency release or raise a lower bound when a vulnerability affects Otto users. Such a constraint is a targeted response, not a substitute for auditing the complete resolved dependency graph. A future advisory can make any previously acceptable version unsafe while it still satisfies the gemspec.
Otto's committed Gemfile.lock makes maintainer development and CI resolution
reproducible. Bundler does not use that lockfile when Otto is installed as a
dependency of another application. Otto's locked and freshly resolved CI jobs
test compatibility; neither job selects or certifies a secure dependency set
for consumer applications.
Consumer lockfile policy
The deployable application is responsible for the final dependency graph. An application using Otto should:
-
Commit its
Gemfile.lockand deploy that exact resolution. -
Make
bundler-auditavailable in application CI, then run it with an updated advisory database on every lockfile change, on a scheduled weekly job, and before each production deployment:bundle-audit check --update -
Treat a relevant advisory as a release blocker. Update the affected gem and re-run the application's tests and audit. For a conservative targeted update, replace
GEM_NAMEwith the affected gem:bundle update --conservative GEM_NAME bundle-audit check --update -
Enable an automated dependency updater, or review
bundle outdatedmanually at least weekly, so patched releases reach the application lockfile. -
Audit the Ruby interpreter, operating system packages, and native libraries separately.
bundler-auditchecks Ruby gems; it does not make an end-of-life Ruby secure.
If the patched dependency version falls outside Otto's declared range,
applications should upgrade Otto when a compatible release is available and
report the blocked update to the maintainers. Do not assume that a successful
bundle install means the resolved bundle has no known vulnerabilities.