Skip to main content
Aimeice Tech
SecurityRuby on RailsCI/CDEngineering Process

Rails Security Upgrades: A Process That Survives Sprint Planning

Rails security upgrades rarely fail from lack of care. They lose to features. Here is the boring process that fixed it: one owner, a cycle, a CI audit, a report.

Andrii Nasadchuk, Founder & CEO · November 07, 2026 · 7 min read

Security upgrades in Rails products rarely fail because a team does not care. They fail because they never win against features in sprint planning. A gem bump has no demo, no customer asking for it, and no one on the roadmap call to defend it. So it slides to next sprint, then the one after.

This autumn we saw that pattern from both sides on Rails products we work on. In this post we break down what went wrong, and the deliberately boring process for Rails security upgrades that we now run instead: one owner, a fixed cycle, a CI audit that informs instead of blocking, and a one-page report a CEO can read in two minutes.

Two ways security work goes wrong

The interesting part is that the two failures look like opposites. One team had too much enforcement, the other had none. Both ended with the same result: security handled in a panic instead of on a schedule.

The audit that blocked every release

One product had bundler-audit wired into CI as a hard gate. Good intention: no known vulnerable gem should ever ship. In practice, a new advisory lands in the Ruby Advisory Database on a random Tuesday, and suddenly every pull request goes red. That includes a one-line copy fix, a hotfix for a payment bug, and a feature the client promised for Friday.

Nothing was merged until someone dropped what they were doing and merged gem updates. That someone was whoever got annoyed first. Upgrades happened under deadline pressure, without reading changelogs, and occasionally broke something unrelated to the advisory. Worse, the team started to see the security check as an obstacle, and the conversation shifted to "how do we skip it" instead of "how do we fix it".

The tokens that never expired, until they did

The opposite case: a long-lived API token for a third-party platform, created years ago, stored in credentials, working fine. Nobody owned it because nothing ever broke. Then the platform changed its policy and started expiring tokens like it. Integrations stopped on the platform's timeline, not ours, and the team spent a day finding out who had admin access to regenerate it.

No audit tool catches this. It is not a vulnerable gem, it is an unowned secret. It only shows up in a process that someone actually runs.

Too much enforcement and no enforcement end in the same place: security handled in a panic instead of on a schedule.

A Rails security upgrade process that is boring on purpose

What works for us now has no clever tooling. It is four habits that make security work predictable enough to survive sprint planning.

1. One owner for security

Not "the team". One named engineer who owns the dependency list, the secrets inventory, and the report. Shared ownership is how a gem upgrade sits in the backlog for four months: everyone agrees it matters, and nobody is accountable for it not happening.

The owner does not have to do every upgrade personally. They decide what goes into the next cycle, make sure it is scheduled, and escalate when something cannot wait. On a small team this is a few hours per cycle, not a full-time role. Rotate it every quarter if you want to spread the knowledge.

2. A regular upgrade cycle with reserved capacity

Security work loses to features when it competes for the same slot every sprint. So we stopped making it compete. Every two weeks, a fixed slice of capacity goes to upgrades before feature work is planned. Typical contents of a cycle:

  • Patch and minor gem updates, grouped, with changelogs read before merging.
  • Any open bundler-audit or Brakeman findings from the last two weeks.
  • One item from the bigger backlog: a Rails minor version, a Ruby version, a deprecated gem replacement.
  • A check of the secrets inventory: what expires soon, what has no owner, what has no rotation date.

Small, frequent upgrades are cheaper than big ones. Going from Rails 7.1 to 7.2 when you are already current on everything else is a focused task. Going from 6.1 to 7.2 after two years of drift is a project with its own budget line.

3. An audit in CI that informs, not blocks

We kept the CI audit and changed what it does. It runs on every push and on a nightly schedule, reports findings to the owner, and does not stop feature merges. The owner triages within the cycle. Real emergencies (a critical advisory in a gem you actually exercise in production, with a public exploit) skip the cycle and get fixed that day.

Here is the shape of it in GitHub Actions:

security-audit:
  runs-on: ubuntu-latest
  continue-on-error: true   # report, don't block feature merges
  steps:
    - uses: actions/checkout@v4
    - uses: ruby/setup-ruby@v1
      with:
        bundler-cache: true
    - run: bundle exec bundler-audit check --update
    - run: bundle exec brakeman --no-pager --quiet

Pair it with a scheduled run so new advisories surface even in weeks when nobody pushes, and route the output somewhere the owner actually reads (a Slack channel, a weekly issue). Dependabot or Renovate can open the update pull requests; the owner decides when they merge.

CI audit mode What happens on a new advisory Side effect
Hard gate Every release stops until gems are bumped. Rushed upgrades, team learns to resent or bypass the check.
No audit Nothing, until a customer, scanner, or platform finds it. Drift compounds into an expensive upgrade project.
Inform + owner Owner triages it into the next cycle, or fixes today if critical. Features keep shipping, security keeps moving.

The trade-off is real: informing instead of blocking means a known advisory can sit in main for up to two weeks. That is acceptable only because a named person is guaranteed to look at it. Without the owner and the cycle, a non-blocking audit is just noise that everyone learns to ignore.

4. A one-page report a CEO can read in two minutes

Security work stays invisible to leadership, which is exactly why it loses prioritisation fights. The fix is a short report after each cycle, written for someone who does not read Gemfiles:

  • Status: green, yellow, or red, in one sentence.
  • Done this cycle: what was upgraded or rotated, in plain words.
  • Open risks: known issues not yet fixed, and why that is acceptable for now.
  • Coming up: expiring tokens and certificates, end-of-life Ruby or Rails versions, with dates.
  • Decision needed: anything that requires budget or a trade-off with the roadmap. Usually empty.

That last line is where the report earns its keep. When a Rails major upgrade needs two sprints, the CEO has already seen it on the "coming up" list for months. It becomes a planned decision instead of a surprise.

Where to start this week

You do not need to roll out all four at once. A reasonable first week:

  1. Name the owner. Write it down where the team will see it.
  2. Run bundle exec bundler-audit check --update and Brakeman once, locally, to see where you stand today.
  3. List every external token and API key the product depends on, with who can regenerate it and when it expires.
  4. Add the non-blocking audit job to CI and a nightly schedule.
  5. Book the first upgrade cycle and send the first one-page report, even if half of it says "unknown".

For reference on what you are upgrading toward, keep the official Rails maintenance policy and the Ruby branch status page bookmarked. Both tell you exactly when your versions stop receiving security fixes.

Security keeps sliding to next sprint?

If you run a Rails product, message us. We will share exactly how we set up the owner, the cycle, the CI audit and the report, or run it for you.

Talk to us

Written by

Andrii Nasadchuk

Founder & CEO

Product engineer. Leads strategy, sales and delivery.

Start here

Tell us what should grow next

Send what you sell and where clients come from now. Within one business day: which agent first, what number it moves, what it costs.

Or run the growth audit first. No email needed to see your score.