diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index 8c51b2cb61a4658b8b429235e4b97a574854ded1..f1d9eda70c4f8c29e0f85f861c64f190a513a9c0 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -1545,6 +1545,12 @@
       changes: ["vendor/gems/devise-pbkdf2-encryptable/**/*"]
     - <<: *if-merge-request-labels-run-all-rspec
 
+.vendor:rules:bundler-checksum:
+  rules:
+    - <<: *if-merge-request
+      changes: ["vendor/gems/bundler-checksum/**/*"]
+    - <<: *if-merge-request-labels-run-all-rspec
+
 ##################
 # Releases rules #
 ##################
diff --git a/.gitlab/ci/vendored-gems.gitlab-ci.yml b/.gitlab/ci/vendored-gems.gitlab-ci.yml
index 468c0e72ede96945fc98c60492d252e8c674c872..de314df298faeb87e278b8d4d3c99dc13ab3c6b5 100644
--- a/.gitlab/ci/vendored-gems.gitlab-ci.yml
+++ b/.gitlab/ci/vendored-gems.gitlab-ci.yml
@@ -69,3 +69,11 @@ vendor devise-pbkdf2-encryptable:
   trigger:
     include: vendor/gems/devise-pbkdf2-encryptable/.gitlab-ci.yml
     strategy: depend
+
+vendor bundler-checksum:
+  extends:
+    - .vendor:rules:bundler-checksum
+  needs: []
+  trigger:
+    include: vendor/gems/bundler-checksum/.gitlab-ci.yml
+    strategy: depend
diff --git a/vendor/gems/bundler-checksum/.gitlab-ci.yml b/vendor/gems/bundler-checksum/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f6bdb73a0392541231603cae32717964a3cea351
--- /dev/null
+++ b/vendor/gems/bundler-checksum/.gitlab-ci.yml
@@ -0,0 +1,28 @@
+workflow:
+  rules:
+    - if: $CI_MERGE_REQUEST_ID
+
+.test:
+  cache:
+    key: bundler-checksum
+    paths:
+      - vendor/gems/bundler-checksum/vendor/ruby
+  before_script:
+    - cd vendor/gems/bundler-checksum
+    - ruby -v                                   # Print out ruby version for debugging
+    - gem install bundler --no-document         # Bundler is not installed with the image
+    - bundle config set --local path 'vendor'   # Install dependencies into ./vendor/ruby
+    - bundle config set with 'development'
+    - bundle config set --local frozen 'true'   # Disallow Gemfile.lock changes on CI
+    - bundle config                             # Show bundler configuration
+    - bundle install -j $(nproc)
+  script:
+    - pushd test/project_with_checksum_lock && scripts/test
+
+test-2.7:
+  image: "ruby:2.7"
+  extends: .test
+
+test-3.0:
+  image: "ruby:3.0"
+  extends: .test
diff --git a/vendor/gems/bundler-checksum/test/project_with_checksum_lock/Gemfile b/vendor/gems/bundler-checksum/test/project_with_checksum_lock/Gemfile
new file mode 100644
index 0000000000000000000000000000000000000000..238bd09669fd3490c40b925f0e01472f09473260
--- /dev/null
+++ b/vendor/gems/bundler-checksum/test/project_with_checksum_lock/Gemfile
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+source 'https://rubygems.org'
+
+if ENV['BUNDLER_CHECKSUM_VERIFICATION_OPT_IN'] # this verification is still experimental
+  $:.unshift(File.expand_path('../../lib', __dir__))
+  require 'bundler-checksum'
+  Bundler::Checksum.patch!
+end
+
+gem 'rails', '~> 6.1.6.1'
diff --git a/vendor/gems/bundler-checksum/test/project_with_checksum_lock/Gemfile.checksum b/vendor/gems/bundler-checksum/test/project_with_checksum_lock/Gemfile.checksum
new file mode 100644
index 0000000000000000000000000000000000000000..cf70611c97ac82e5d306fdb054a12ae1b66a7661
--- /dev/null
+++ b/vendor/gems/bundler-checksum/test/project_with_checksum_lock/Gemfile.checksum
@@ -0,0 +1,54 @@
+[
+{"name":"actioncable","version":"6.1.6.1","platform":"ruby","checksum":"11f079141cf032026881e4a79ae0cc93753351089c1b6ca1ed30a8a6a21f961b"},
+{"name":"actionmailbox","version":"6.1.6.1","platform":"ruby","checksum":"a4cc16fe634c9de4e22669fc4bf20d5b84f65039c7e3d7308c804b82726d03d2"},
+{"name":"actionmailer","version":"6.1.6.1","platform":"ruby","checksum":"13964bff4a75efd705304cb7aeb71380a4b11d404c7304b67f3bc3208cde12a7"},
+{"name":"actionpack","version":"6.1.6.1","platform":"ruby","checksum":"f3e0a82a62aa36fecadbacbb266e38338da032f18aaf97674f335671b420bdd4"},
+{"name":"actiontext","version":"6.1.6.1","platform":"ruby","checksum":"ff26b96769b6f4bdf3c0e74f613b232b2cdab7e46f1433c9cfa4fdcd081afac0"},
+{"name":"actionview","version":"6.1.6.1","platform":"ruby","checksum":"a87fc7d2c4fe9b6357492a3ee361be8169f3f319f47bf70fda1b1718b944d06b"},
+{"name":"activejob","version":"6.1.6.1","platform":"ruby","checksum":"9efee4499d31aaaab73b843a09564d4a2aabcd51c2088361a92e08766ab0db65"},
+{"name":"activemodel","version":"6.1.6.1","platform":"ruby","checksum":"239953365a7da4bcb9a3819b8ac2557a58a3ba89ddd36bee9bb3eca818e4a3e2"},
+{"name":"activerecord","version":"6.1.6.1","platform":"ruby","checksum":"82f74804ab34ea549fd593e5ced68c32426564786127d2de9b933ba78467d0b0"},
+{"name":"activestorage","version":"6.1.6.1","platform":"ruby","checksum":"3fbf4c355a69a46e14676004ad8e06245bdce7f96858e72782715218326aafc5"},
+{"name":"activesupport","version":"6.1.6.1","platform":"ruby","checksum":"5fc9fd6fe6f755e7523bb3aaf4370fb91a8416b39e3202939fd8bded4fec606d"},
+{"name":"builder","version":"3.2.4","platform":"ruby","checksum":"99caf08af60c8d7f3a6b004029c4c3c0bdaebced6c949165fe98f1db27fbbc10"},
+{"name":"concurrent-ruby","version":"1.1.10","platform":"ruby","checksum":"244cb1ca0d91ec2c15ca2209507c39fb163336994428e16fbd3f465c87bd8e68"},
+{"name":"crass","version":"1.0.6","platform":"ruby","checksum":"dc516022a56e7b3b156099abc81b6d2b08ea1ed12676ac7a5657617f012bd45d"},
+{"name":"erubi","version":"1.11.0","platform":"ruby","checksum":"fda72d577feaf3bdcd646d33fa630be5f92f48e179a9278e4175a9cec20e7f85"},
+{"name":"globalid","version":"1.0.0","platform":"ruby","checksum":"1253641b1dc3392721c964351773755d75135d3d3c5cc65d88b0a3880a60bed8"},
+{"name":"i18n","version":"1.12.0","platform":"ruby","checksum":"91e3cc1b97616d308707eedee413d82ee021d751c918661fb82152793e64aced"},
+{"name":"loofah","version":"2.18.0","platform":"ruby","checksum":"61975a247a6aeb8f09ac5a3430305451efc4525c0b9b79c05feaec35a8b9d5a3"},
+{"name":"mail","version":"2.7.1","platform":"ruby","checksum":"ec2a3d489f7510b90d8eaa3f6abaad7038cf1d663cdf8ee66d0214a0bdf99c03"},
+{"name":"marcel","version":"1.0.2","platform":"ruby","checksum":"a013b677ef46cbcb49fd5c59b3d35803d2ee04dd75d8bfdc43533fc5a31f7e4e"},
+{"name":"method_source","version":"1.0.0","platform":"ruby","checksum":"d779455a2b5666a079ce58577bfad8534f571af7cec8107f4dce328f0981dede"},
+{"name":"mini_mime","version":"1.1.2","platform":"ruby","checksum":"a54aec0cc7438a03a850adb00daca2bdb60747f839e28186994df057cea87151"},
+{"name":"minitest","version":"5.16.2","platform":"ruby","checksum":"c1be0c6b57fab451faa08e74ffa71e7d6a259b90f4bacb881c7f4808ec8b4991"},
+{"name":"nio4r","version":"2.5.8","platform":"java","checksum":"b2b1800f6bf7ce4b797ca8b639ad278a99c9c904fb087a91d944f38e4bd71401"},
+{"name":"nio4r","version":"2.5.8","platform":"ruby","checksum":"3becb4ad95ab8ac0a9bd2e1b16466869402be62848082bf6329ae9091f276676"},
+{"name":"nokogiri","version":"1.13.8","platform":"aarch64-linux","checksum":"d6b2c45a57738f12fe27783939fe1394e7049246288c7770d3b1fee7f49432a6"},
+{"name":"nokogiri","version":"1.13.8","platform":"arm64-darwin","checksum":"00217e48a6995e81dd83014325c0ea0b015023a8922c7bdb2ef1416aa87c1f43"},
+{"name":"nokogiri","version":"1.13.8","platform":"java","checksum":"9d04c616900e2b5118e501436ebb9bc48520d08f3695d012a314006e28082f72"},
+{"name":"nokogiri","version":"1.13.8","platform":"ruby","checksum":"79c279298b2f22fd4e760f49990c7930436bac1b1cfeff7bacff192f30edea3c"},
+{"name":"nokogiri","version":"1.13.8","platform":"x64-mingw-ucrt","checksum":"98f7dac7583f07a84ec3fcc01dc03a66fce10f412cd363fce7de749acdb2a42d"},
+{"name":"nokogiri","version":"1.13.8","platform":"x64-mingw32","checksum":"117a71b37f2e1d774a9f031d393e72d5d04b92af8036e0c1a8dd509c247b2013"},
+{"name":"nokogiri","version":"1.13.8","platform":"x86-linux","checksum":"6d04342456edfb8fbc041d0c2cf5a59baaa7aacdda414b2333100b02f85d441d"},
+{"name":"nokogiri","version":"1.13.8","platform":"x86-mingw32","checksum":"0529d558b4280a55bc7af500d3d4d590b7c059c814a0cea52e4e18cb30c25d15"},
+{"name":"nokogiri","version":"1.13.8","platform":"x86_64-darwin","checksum":"8966d79e687b271df87a4b240456597c43cd98584e3f783fc35de4f066486421"},
+{"name":"nokogiri","version":"1.13.8","platform":"x86_64-linux","checksum":"344f1bc66feac787e5b2053c6e9095d1f33605083e58ddf2b8d4eef257bccc5f"},
+{"name":"racc","version":"1.6.0","platform":"java","checksum":"d449a3c279026451b9fd5f34e829dc5f6e0ef6b9b472b7ff89fd3877fe8fe8cf"},
+{"name":"racc","version":"1.6.0","platform":"ruby","checksum":"2dede3b136eeabd0f7b8c9356b958b3d743c00158e2615acab431af141354551"},
+{"name":"rack","version":"2.2.4","platform":"ruby","checksum":"ea2232b638cbd919129c8c8ad8012ecaccc09f848152a7e705d2139d0137ac2b"},
+{"name":"rack-test","version":"2.0.2","platform":"ruby","checksum":"adadd0e957f63a34199a9fdf905a920a0b0a50795735095b4ac4bd3c13385466"},
+{"name":"rails","version":"6.1.6.1","platform":"ruby","checksum":"17024921a3913fb341f584542b06adf6bb12977a8b92d5fce093c3996c963686"},
+{"name":"rails-dom-testing","version":"2.0.3","platform":"ruby","checksum":"b140c4f39f6e609c8113137b9a60dfc2ecb89864e496f87f23a68b3b8f12d8d1"},
+{"name":"rails-html-sanitizer","version":"1.4.3","platform":"ruby","checksum":"2ebba6ad9a0b100f79fda853a46851e7664febe1728223f9734281e0d55940d6"},
+{"name":"railties","version":"6.1.6.1","platform":"ruby","checksum":"bafecdf2dcbe4ea44e1ab7081fd797aa87ae9bbcd0f3a4372b662a1b93949733"},
+{"name":"rake","version":"13.0.6","platform":"ruby","checksum":"5ce4bf5037b4196c24ac62834d8db1ce175470391026bd9e557d669beeb19097"},
+{"name":"sprockets","version":"4.1.1","platform":"ruby","checksum":"68b10b0e574fc2a080e4779d025bf39bc7a20bc8659e32f827cccce9581348e2"},
+{"name":"sprockets-rails","version":"3.4.2","platform":"ruby","checksum":"36d6327757ccf7460a00d1d52b2d5ef0019a4670503046a129fa1fb1300931ad"},
+{"name":"thor","version":"1.2.1","platform":"ruby","checksum":"b1752153dc9c6b8d3fcaa665e9e1a00a3e73f28da5e238b81c404502e539d446"},
+{"name":"tzinfo","version":"2.0.5","platform":"ruby","checksum":"c5352fd901544d396745d013f46a04ae2ed081ce806d942099825b7c2b09a167"},
+{"name":"websocket-driver","version":"0.7.5","platform":"java","checksum":"fffa83aa188e9ac90e32a385832ec9d26acdf019538e1c7d703f2c8a323b39c8"},
+{"name":"websocket-driver","version":"0.7.5","platform":"ruby","checksum":"a280c3f44dcbb0323d58bc78dc49350c05d589ab7d13267fcff08d9d5ae76b28"},
+{"name":"websocket-extensions","version":"0.1.5","platform":"ruby","checksum":"1c6ba63092cda343eb53fc657110c71c754c56484aad42578495227d717a8241"},
+{"name":"zeitwerk","version":"2.6.0","platform":"ruby","checksum":"6cb2ee4645c6e597640d6f2d8cc91a59a6699ab38896a5c3fac3eefeb5c84d76"}
+]
diff --git a/vendor/gems/bundler-checksum/test/project_with_checksum_lock/Gemfile.lock b/vendor/gems/bundler-checksum/test/project_with_checksum_lock/Gemfile.lock
new file mode 100644
index 0000000000000000000000000000000000000000..8f4bb5fa40db82be627cdaf1ef70024daea3ff37
--- /dev/null
+++ b/vendor/gems/bundler-checksum/test/project_with_checksum_lock/Gemfile.lock
@@ -0,0 +1,139 @@
+GEM
+  remote: https://rubygems.org/
+  specs:
+    actioncable (6.1.6.1)
+      actionpack (= 6.1.6.1)
+      activesupport (= 6.1.6.1)
+      nio4r (~> 2.0)
+      websocket-driver (>= 0.6.1)
+    actionmailbox (6.1.6.1)
+      actionpack (= 6.1.6.1)
+      activejob (= 6.1.6.1)
+      activerecord (= 6.1.6.1)
+      activestorage (= 6.1.6.1)
+      activesupport (= 6.1.6.1)
+      mail (>= 2.7.1)
+    actionmailer (6.1.6.1)
+      actionpack (= 6.1.6.1)
+      actionview (= 6.1.6.1)
+      activejob (= 6.1.6.1)
+      activesupport (= 6.1.6.1)
+      mail (~> 2.5, >= 2.5.4)
+      rails-dom-testing (~> 2.0)
+    actionpack (6.1.6.1)
+      actionview (= 6.1.6.1)
+      activesupport (= 6.1.6.1)
+      rack (~> 2.0, >= 2.0.9)
+      rack-test (>= 0.6.3)
+      rails-dom-testing (~> 2.0)
+      rails-html-sanitizer (~> 1.0, >= 1.2.0)
+    actiontext (6.1.6.1)
+      actionpack (= 6.1.6.1)
+      activerecord (= 6.1.6.1)
+      activestorage (= 6.1.6.1)
+      activesupport (= 6.1.6.1)
+      nokogiri (>= 1.8.5)
+    actionview (6.1.6.1)
+      activesupport (= 6.1.6.1)
+      builder (~> 3.1)
+      erubi (~> 1.4)
+      rails-dom-testing (~> 2.0)
+      rails-html-sanitizer (~> 1.1, >= 1.2.0)
+    activejob (6.1.6.1)
+      activesupport (= 6.1.6.1)
+      globalid (>= 0.3.6)
+    activemodel (6.1.6.1)
+      activesupport (= 6.1.6.1)
+    activerecord (6.1.6.1)
+      activemodel (= 6.1.6.1)
+      activesupport (= 6.1.6.1)
+    activestorage (6.1.6.1)
+      actionpack (= 6.1.6.1)
+      activejob (= 6.1.6.1)
+      activerecord (= 6.1.6.1)
+      activesupport (= 6.1.6.1)
+      marcel (~> 1.0)
+      mini_mime (>= 1.1.0)
+    activesupport (6.1.6.1)
+      concurrent-ruby (~> 1.0, >= 1.0.2)
+      i18n (>= 1.6, < 2)
+      minitest (>= 5.1)
+      tzinfo (~> 2.0)
+      zeitwerk (~> 2.3)
+    builder (3.2.4)
+    concurrent-ruby (1.1.10)
+    crass (1.0.6)
+    erubi (1.11.0)
+    globalid (1.0.0)
+      activesupport (>= 5.0)
+    i18n (1.12.0)
+      concurrent-ruby (~> 1.0)
+    loofah (2.18.0)
+      crass (~> 1.0.2)
+      nokogiri (>= 1.5.9)
+    mail (2.7.1)
+      mini_mime (>= 0.1.1)
+    marcel (1.0.2)
+    method_source (1.0.0)
+    mini_mime (1.1.2)
+    minitest (5.16.2)
+    nio4r (2.5.8)
+    nokogiri (1.13.8-arm64-darwin)
+      racc (~> 1.4)
+    nokogiri (1.13.8-x86_64-linux)
+      racc (~> 1.4)
+    racc (1.6.0)
+    rack (2.2.4)
+    rack-test (2.0.2)
+      rack (>= 1.3)
+    rails (6.1.6.1)
+      actioncable (= 6.1.6.1)
+      actionmailbox (= 6.1.6.1)
+      actionmailer (= 6.1.6.1)
+      actionpack (= 6.1.6.1)
+      actiontext (= 6.1.6.1)
+      actionview (= 6.1.6.1)
+      activejob (= 6.1.6.1)
+      activemodel (= 6.1.6.1)
+      activerecord (= 6.1.6.1)
+      activestorage (= 6.1.6.1)
+      activesupport (= 6.1.6.1)
+      bundler (>= 1.15.0)
+      railties (= 6.1.6.1)
+      sprockets-rails (>= 2.0.0)
+    rails-dom-testing (2.0.3)
+      activesupport (>= 4.2.0)
+      nokogiri (>= 1.6)
+    rails-html-sanitizer (1.4.3)
+      loofah (~> 2.3)
+    railties (6.1.6.1)
+      actionpack (= 6.1.6.1)
+      activesupport (= 6.1.6.1)
+      method_source
+      rake (>= 12.2)
+      thor (~> 1.0)
+    rake (13.0.6)
+    sprockets (4.1.1)
+      concurrent-ruby (~> 1.0)
+      rack (> 1, < 3)
+    sprockets-rails (3.4.2)
+      actionpack (>= 5.2)
+      activesupport (>= 5.2)
+      sprockets (>= 3.0.0)
+    thor (1.2.1)
+    tzinfo (2.0.5)
+      concurrent-ruby (~> 1.0)
+    websocket-driver (0.7.5)
+      websocket-extensions (>= 0.1.0)
+    websocket-extensions (0.1.5)
+    zeitwerk (2.6.0)
+
+PLATFORMS
+  arm64-darwin-21
+  x86_64-linux
+
+DEPENDENCIES
+  rails (~> 6.1.6.1)
+
+BUNDLED WITH
+   2.3.19
diff --git a/vendor/gems/bundler-checksum/test/project_with_checksum_lock/scripts/test b/vendor/gems/bundler-checksum/test/project_with_checksum_lock/scripts/test
new file mode 100755
index 0000000000000000000000000000000000000000..bb2564492266b74ffbacacda1d48e8fd7339a639
--- /dev/null
+++ b/vendor/gems/bundler-checksum/test/project_with_checksum_lock/scripts/test
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+set -x
+set -e
+
+# Check there's no differences after re-initialising
+ruby -I ../../lib ../../bin/bundler-checksum init
+git diff --exit-code Gemfile.checksum
+
+# Verify against rubygems.org
+ruby -I ../../lib ../../bin/bundler-checksum verify
+
+# Test installing with bundler-checksum
+export BUNDLER_CHECKSUM_VERIFICATION_OPT_IN=1
+bundle install