Your dependencies are your attack surface
A modest Rails app pulls in a hundred-odd gems and several hundred transitive ones. Almost none were chosen by anyone.
Run bundle list and count. Then consider that each of those has its own dependencies,
each maintained by someone you have never met, each with the same access to your process
as the code you wrote.
Two different risks
Known vulnerabilities are the manageable one: a CVE is published, a patched version
exists, you upgrade. bundler-audit checks your lockfile against the advisory database
and should run in CI, because a report nobody reads is not a control.
Compromise is the harder one — a maintainer account taken over, or a package that was always malicious. There is no advisory yet, and the code arrives looking legitimate.
What reduces the second risk
Lockfiles, committed and enforced. A lockfile pins exact versions and checksums; bundle
install --deployment refuses to deviate from it. Without that, your build resolves
dependencies fresh and can pick up something new without anyone noticing.
Fewer dependencies. Every gem is a trust decision. A gem that saves twenty lines of code costs you a permanent supply-chain relationship, and that arithmetic is worth doing explicitly for small utilities.
Attention at add-time. When adding a dependency, five minutes of looking — is it maintained, does it have real usage, how many transitive dependencies does it drag in — is the cheapest security work available. It is also the only moment anyone naturally looks.
Adding a dependency is the last time anyone will evaluate it. Spend five minutes then, because you will not spend them later.
Upgrades are a risk decision either way
Upgrading promptly reduces exposure to known vulnerabilities and increases exposure to newly-introduced bugs. Waiting does the reverse.
The practical position: security patches immediately, minor versions on a regular cadence, majors deliberately with time to test. What does not work is the common alternative of never upgrading, then attempting a two-year jump under incident pressure.
The build is part of the chain
A compromised dependency runs during install and build, not just at runtime. Anything in that environment — credentials, tokens, the ability to modify the artefact — is within reach.
Which argues for build environments with narrow credentials, and for not exposing production secrets during a build that installs third-party code.
Know what you ship
A dependency inventory — a bill of materials — turns "are we affected by this advisory?" from an afternoon of investigation into a query. When the next widely-exploited library bug lands, the teams that answer quickly are the ones that already knew what they had.