Poisoned Pipeline / Techniques / T0227
Load code from the package manager's plugin directory
Package managers execute more than the package's declared install
hooks. RubyGems treats a file named rubygems_plugin.rb at the root of
a gem's require path — normally lib/rubygems_plugin.rb — as a plugin:
at the end of gem install it writes a loader for that file into its
own plugins directory, and it loads everything in that directory on
every later gem command, including read-only ones such as gem list,
gem search and gem -v, and commands concerning unrelated gems. No
separate plugin declaration is required, so a reviewer looking for an
explicit execution hook sees only a file in lib/. Plugin-loading
exceptions are reported as warnings, so the command carries on after
a plugin fails, and the plugin runs again on each command for as long
as the gem stays installed.
That makes the plugin directory a persistence surface that survives
the install that created it and fires on operations a developer does
not think of as code execution. It differs from an install script in
both timing and lifetime: the code runs after the transaction the
developer consented to, and keeps running. Gems Bundler installs into
vendor/bundle or a custom BUNDLE_PATH are the exception — a plain gem
list does not load their plugins, but bundle exec gem list does.
Distinct from T0151, which is a declared build or lifecycle hook that
runs once at install; from T0159, which is the artifact executing at
all; and from T0211, where a registry-adjacent service is abused as
the execution host. Here the package manager's own command path loads
the attacker's file on every invocation, with nothing in the package
manifest pointing at it.
Where this idea came from
From Aikido's 5 November 2026 review of install-time execution in RubyGems. A file named lib/rubygems_plugin.rb needs no declaration in the gemspec, is loaded at the end of gem install, and is loaded again by every later gem command including gem list, gem search and gem -v, with failures demoted to warnings. Distinct from T0151, which is a declared build hook that runs once at install.
Mitigations
None linked yet.
Detections
None linked yet.