Puma service worker crashes when trying to upload ECDSA point at infinity

⚠️ Please read the process on how to fix security issues before starting to work on the issue. Vulnerabilities must be fixed in a security mirror.

Summary

Uploading an ECDSA key that resembles the "point at infinity" causes the assigned puma worker to crash with a segfault, consuming excessive CPU resources (factor 2-3 over a "normal" invalid key).

There might be other implications that I am not aware of, hence reporting this as a security vulnerability to err on the side of caution.

Steps to reproduce

The bug can be reproduced by trying to upload an ECDSA key that resembles the point at infinity, a special point that is used with common elliptic curves such as NIST P-256. The point at infinity is encoded as a single null byte according to X9.62 Section 4.3.6. You may use the following base64 encoded SSH public key to reproduce the bug:

ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAAABAA== ecdsa-point-at-infinity

What is the current bug behavior?

The related puma worker crashes with a segfault, and the user is shown a 502 error page. The crash consumes significantly more CPU resources than other SSH public key upload operations.

What is the expected correct behavior?

The key should be rejected without the underlying worker crashing. The user should be displayed an error that the point at infinity is no valid public key to use with ECDSA. The CPU consumption should be in line with other SSH public key uploads.

Relevant logs and/or screenshots

/opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/ssh_public_key.rb:111: [BUG] Segmentation fault at 0x0000000000000018
ruby 3.2.5 (2024-07-26 revision 31d0f1a2e7) [x86_64-linux]

-- Control frame information -----------------------------------------------
c:0219 p:---- s:1452 e:001451 CFUNC  :group
c:0218 p:0091 s:1448 e:001447 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/ssh_public_key.rb:111
c:0217 p:0042 s:1444 e:001443 METHOD /opt/gitlab/embedded/service/gitlab-rails/app/validators/ssh_key_validator.rb:19
c:0216 p:0061 s:1435 e:001434 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activemodel-7.1.5.1/lib/active_model/validator.rb:155 [FINISH]
c:0215 p:---- s:1430 e:001429 CFUNC  :each
c:0214 p:0006 s:1426 e:001425 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activemodel-7.1.5.1/lib/active_model/validator.rb:151
c:0213 p:0019 s:1421 e:001420 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/callbacks.rb:426
c:0212 p:0009 s:1415 e:001414 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/callbacks.rb:202
c:0211 p:0004 s:1412 e:001411 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/callbacks.rb:707 [FINISH]
c:0210 p:---- s:1409 e:001408 CFUNC  :catch
c:0209 p:0010 s:1404 e:001403 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/callbacks.rb:706
c:0208 p:0040 s:1398 E:0015c8 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/callbacks.rb:203
c:0207 p:0006 s:1389 e:001388 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/callbacks.rb:598 [FINISH]
c:0206 p:---- s:1385 e:001384 CFUNC  :each
c:0205 p:0006 s:1381 e:001380 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/callbacks.rb:598
c:0204 p:0060 s:1376 e:001375 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/callbacks.rb:109
c:0203 p:0009 s:1366 e:001365 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/callbacks.rb:952
c:0202 p:0003 s:1361 e:001360 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activemodel-7.1.5.1/lib/active_model/validations.rb:441
c:0201 p:0004 s:1357 e:001356 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activemodel-7.1.5.1/lib/active_model/validations/callbacks.rb:115
c:0200 p:0084 s:1354 e:001352 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/callbacks.rb:110
c:0199 p:0009 s:1343 e:001342 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/callbacks.rb:952
c:0198 p:0004 s:1338 e:001337 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activemodel-7.1.5.1/lib/active_model/validations/callbacks.rb:115
c:0197 p:0028 s:1334 e:001333 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activemodel-7.1.5.1/lib/active_model/validations.rb:366
c:0196 p:0018 s:1328 e:001327 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activerecord-7.1.5.1/lib/active_record/validations.rb:72
c:0195 p:0027 s:1322 e:001321 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activerecord-7.1.5.1/lib/active_record/validations.rb:88
c:0194 p:0005 s:1317 e:001316 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activerecord-7.1.5.1/lib/active_record/validations.rb:49
c:0193 p:0006 s:1312 e:001311 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activerecord-7.1.5.1/lib/active_record/transactions.rb:309
c:0192 p:0020 s:1309 e:001308 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activerecord-7.1.5.1/lib/active_record/transactions.rb:365
c:0191 p:0027 s:1306 e:001305 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activerecord-7.1.5.1/lib/active_record/connection_adapters/abstract/database_stat [FINISH]
c:0190 p:---- s:1297 e:001296 CFUNC  :public_send
c:0189 p:0012 s:1292 e:001291 BLOCK  /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/database/load_balancing/connection_proxy.rb:127
c:0188 p:0031 s:1288 e:001287 BLOCK  /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/database/load_balancing/load_balancer.rb:145
c:0187 p:0007 s:1282 e:001281 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/database/load_balancing/load_balancer.rb:232
c:0186 p:0067 s:1272 e:001271 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/database/load_balancing/load_balancer.rb:135
c:0185 p:0019 s:1265 e:001264 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/database/load_balancing/connection_proxy.rb:126
c:0184 p:0067 s:1258 e:001257 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/database/load_balancing/connection_proxy.rb:78
c:0183 p:0023 s:1251 e:001250 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activerecord-7.1.5.1/lib/active_record/transactions.rb:361
c:0182 p:0004 s:1244 e:001243 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activerecord-7.1.5.1/lib/active_record/transactions.rb:309
c:0181 p:0022 s:1239 e:001238 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activerecord-7.1.5.1/lib/active_record/suppressor.rb:52
c:0180 p:0033 s:1234 e:001233 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activerecord-7.1.5.1/lib/active_record/associations/collection_association.rb:373
c:0179 p:0024 s:1226 e:001225 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activerecord-7.1.5.1/lib/active_record/associations/has_many_association.rb:63
c:0178 p:0012 s:1219 e:001218 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activerecord-7.1.5.1/lib/active_record/associations/collection_association.rb:358
c:0177 p:0068 s:1216 e:001215 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activerecord-7.1.5.1/lib/active_record/associations/collection_association.rb:462
c:0176 p:0022 s:1206 e:001205 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activerecord-7.1.5.1/lib/active_record/associations/collection_association.rb:278
c:0175 p:0010 s:1197 e:001196 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activerecord-7.1.5.1/lib/active_record/associations/collection_association.rb:357
c:0174 p:0023 s:1193 e:001192 BLOCK  /opt/gitlab/embedded/service/gitlab-rails/app/models/concerns/cross_database_modification.rb:91
c:0173 p:0012 s:1189 e:001188 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activerecord-7.1.5.1/lib/active_record/connection_adapters/abstract/transaction.r
c:0172 p:0002 s:1182 e:001181 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/concurrency/null_lock.rb:9
c:0171 p:0008 s:1178 e:001177 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activerecord-7.1.5.1/lib/active_record/connection_adapters/abstract/transaction.r
c:0170 p:0042 s:1171 e:001170 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activerecord-7.1.5.1/lib/active_record/connection_adapters/abstract/database_stat [FINISH]
c:0169 p:---- s:1162 e:001161 CFUNC  :public_send
c:0168 p:0012 s:1157 e:001156 BLOCK  /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/database/load_balancing/connection_proxy.rb:127
c:0167 p:0031 s:1153 e:001152 BLOCK  /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/database/load_balancing/load_balancer.rb:145
c:0166 p:0007 s:1147 e:001146 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/database/load_balancing/load_balancer.rb:232
c:0165 p:0067 s:1137 e:001136 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/database/load_balancing/load_balancer.rb:135
c:0164 p:0019 s:1130 e:001129 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/database/load_balancing/connection_proxy.rb:126
c:0163 p:0067 s:1123 e:001122 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/database/load_balancing/connection_proxy.rb:78
c:0162 p:0011 s:1116 e:001115 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activerecord-7.1.5.1/lib/active_record/transactions.rb:212
c:0161 p:0041 s:1110 e:001109 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/database.rb:397
c:0160 p:0006 s:1103 e:001102 METHOD /opt/gitlab/embedded/service/gitlab-rails/app/models/concerns/cross_database_modification.rb:82
c:0159 p:0011 s:1097 e:001096 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activerecord-7.1.5.1/lib/active_record/associations/collection_association.rb:314
c:0158 p:0053 s:1092 e:001091 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activerecord-7.1.5.1/lib/active_record/associations/collection_association.rb:355
c:0157 p:0030 s:1084 e:001082 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activerecord-7.1.5.1/lib/active_record/associations/has_many_association.rb:147
c:0156 p:0012 s:1077 e:001076 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activerecord-7.1.5.1/lib/active_record/associations/association.rb:207
c:0155 p:0015 s:1071 e:001070 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activerecord-7.1.5.1/lib/active_record/associations/collection_proxy.rb:350
c:0154 p:0010 s:1065 e:001064 METHOD /opt/gitlab/embedded/service/gitlab-rails/app/services/keys/create_service.rb:15
c:0153 p:0019 s:1060 e:001059 METHOD /opt/gitlab/embedded/service/gitlab-rails/app/controllers/user_settings/ssh_keys_controller.rb:18
c:0152 p:0010 s:1056 e:001055 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/action_controller/metal/basic_implicit_render.rb:6
c:0151 p:0011 s:1049 e:001048 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/abstract_controller/base.rb:224
c:0150 p:0022 s:1042 e:001041 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/action_controller/metal/rendering.rb:165
c:0149 p:0008 s:1037 e:001036 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/abstract_controller/callbacks.rb:259
c:0148 p:0048 s:1034 e:001032 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/callbacks.rb:121
c:0147 p:0008 s:1024 e:001023 METHOD /opt/gitlab/embedded/service/gitlab-rails/app/controllers/application_controller.rb:492
c:0146 p:0127 s:1019 e:001018 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/callbacks.rb:130
c:0145 p:0013 s:1010 e:001009 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/session.rb:11
c:0144 p:0019 s:1004 e:001003 METHOD /opt/gitlab/embedded/service/gitlab-rails/app/controllers/application_controller.rb:483
c:0143 p:0127 s:0999 e:000998 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/callbacks.rb:130
c:0142 p:0013 s:0990 e:000989 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/i18n.rb:116
c:0141 p:0014 s:0984 e:000983 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/i18n.rb:122
c:0140 p:0016 s:0978 e:000977 METHOD /opt/gitlab/embedded/service/gitlab-rails/app/controllers/application_controller.rb:474
c:0139 p:0127 s:0973 e:000972 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/callbacks.rb:130
c:0138 p:0060 s:0964 E:002018 METHOD /opt/gitlab/embedded/service/gitlab-rails/app/controllers/application_controller.rb:463
c:0137 p:0127 s:0959 e:000958 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/callbacks.rb:130
c:0136 p:0008 s:0950 e:000949 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/ip_address_state.rb:11
c:0135 p:0013 s:0945 e:000944 METHOD /opt/gitlab/embedded/service/gitlab-rails/app/controllers/application_controller.rb:469
c:0134 p:0127 s:0940 e:000939 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/callbacks.rb:130
c:0133 p:0008 s:0931 e:000930 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/marginalia-1.11.1/lib/marginalia.rb:109
c:0132 p:0127 s:0927 e:000926 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/callbacks.rb:130
c:0131 p:0102 s:0918 e:000917 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/sentry-rails-5.23.0/lib/sentry/rails/controller_transaction.rb:34
c:0130 p:0029 s:0912 e:000911 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/sentry-ruby-5.23.0/lib/sentry/hub.rb:138
c:0129 p:0021 s:0902 e:000901 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/sentry-ruby-5.23.0/lib/sentry-ruby.rb:515
c:0128 p:0048 s:0896 e:000895 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/sentry-rails-5.23.0/lib/sentry/rails/controller_transaction.rb:18
c:0127 p:0127 s:0891 e:000890 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/callbacks.rb:130
c:0126 p:0110 s:0882 E:002390 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/callbacks.rb:141
c:0125 p:0006 s:0872 E:001da8 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/abstract_controller/callbacks.rb:258
c:0124 p:0008 s:0865 e:000864 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/action_controller/metal/rescue.rb:25
c:0123 p:0009 s:0859 e:000858 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/action_controller/metal/instrumentation.rb:74
c:0122 p:0010 s:0853 e:000852 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/notifications.rb:206
c:0121 p:0027 s:0850 e:000849 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/notifications/instrumenter.rb:58
c:0120 p:0023 s:0842 e:000841 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/notifications.rb:206
c:0119 p:0084 s:0836 e:000835 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/action_controller/metal/instrumentation.rb:73
c:0118 p:0017 s:0830 e:000829 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/action_controller/metal/params_wrapper.rb:261
c:0117 p:0015 s:0825 e:000824 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activerecord-7.1.5.1/lib/active_record/railties/controller_runtime.rb:32
c:0116 p:0063 s:0819 e:000818 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/abstract_controller/base.rb:160
c:0115 p:0035 s:0812 e:000811 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionview-7.1.5.1/lib/action_view/rendering.rb:40
c:0114 p:0017 s:0804 e:000803 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/action_controller/metal.rb:227
c:0113 p:0011 s:0797 e:000796 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/action_controller/metal.rb:307
c:0112 p:0090 s:0793 e:000792 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/action_controller_static_context.rb:23
c:0111 p:0021 s:0783 E:001178 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/action_controller/metal.rb:307
c:0110 p:0010 s:0776 e:000775 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/action_dispatch/routing/route_set.rb:49
c:0109 p:0036 s:0768 e:000767 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/action_dispatch/routing/route_set.rb:32
c:0108 p:0122 s:0760 e:000759 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/action_dispatch/journey/router.rb:51
c:0107 p:0041 s:0747 e:000746 BLOCK  /opt/gitlab/embedded/service/gitlab-rails/config/initializers/action_dispatch_journey_router.rb:52 [FINISH]
c:0106 p:---- s:0741 e:000740 CFUNC  :map!
c:0105 p:0057 s:0737 e:000736 METHOD /opt/gitlab/embedded/service/gitlab-rails/config/initializers/action_dispatch_journey_router.rb:25
c:0104 p:0006 s:0730 e:000729 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/action_dispatch/journey/router.rb:32
c:0103 p:0027 s:0725 e:000724 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/action_dispatch/routing/route_set.rb:882
c:0102 p:0038 s:0719 e:000718 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/gitlab-experiment-0.9.1/lib/gitlab/experiment/middleware.rb:19
c:0101 p:0106 s:0713 e:000712 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/flipper-0.28.3/lib/flipper/middleware/memoizer.rb:72
c:0100 p:0020 s:0706 e:000705 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/flipper-0.28.3/lib/flipper/middleware/memoizer.rb:37
c:0099 p:0013 s:0700 e:000699 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/metrics/elasticsearch_rack_middleware.rb:16
c:0098 p:0007 s:0694 e:000693 BLOCK  /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/sidekiq_shard_awareness_validation.rb:20
c:0097 p:0023 s:0691 e:000690 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/sidekiq_sharding/validator.rb:42
c:0096 p:0038 s:0686 e:000685 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/sidekiq_shard_awareness_validation.rb:20
c:0095 p:0022 s:0679 e:000678 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/memory_report.rb:13
c:0094 p:0022 s:0670 e:000669 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/speedscope.rb:13
c:0093 p:0017 s:0661 e:000660 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/database/load_balancing/rack_middleware.rb:23
c:0092 p:0090 s:0655 e:000654 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/rails_queue_duration.rb:33
c:0091 p:0027 s:0646 e:000645 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/etag_caching/middleware.rb:21
c:0090 p:0007 s:0636 e:000635 BLOCK  /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/metrics/rack_middleware.rb:16
c:0089 p:0018 s:0633 e:000632 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/metrics/web_transaction.rb:46
c:0088 p:0013 s:0623 e:000622 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/metrics/rack_middleware.rb:16
c:0087 p:0028 s:0615 e:000614 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/go.rb:21
c:0086 p:0007 s:0608 e:000607 BLOCK  /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/query_analyzer.rb:11
c:0085 p:0014 s:0605 e:000604 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/database/query_analyzer.rb:83
c:0084 p:0007 s:0599 e:000598 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/query_analyzer.rb:11
c:0083 p:0007 s:0594 e:000593 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/ci/job_token/middleware.rb:11
c:0082 p:0007 s:0588 e:000587 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/batch-loader-2.0.5/lib/batch_loader/middleware.rb:11
c:0081 p:0024 s:0583 e:000582 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/rack-attack-6.7.0/lib/rack/attack.rb:103
c:0080 p:0020 s:0577 e:000576 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/apollo_upload_server-2.1.6/lib/apollo_upload_server/middleware.rb:19
c:0079 p:0021 s:0569 e:000568 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/multipart.rb:173
c:0078 p:0163 s:0561 e:000560 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/rack-attack-6.7.0/lib/rack/attack.rb:127
c:0077 p:0016 s:0555 e:000554 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/warden-1.2.9/lib/warden/manager.rb:36 [FINISH]
c:0076 p:---- s:0552 e:000551 CFUNC  :catch
c:0075 p:0050 s:0547 e:000546 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/warden-1.2.9/lib/warden/manager.rb:34
c:0074 p:0156 s:0541 e:000540 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/rack-cors-2.0.2/lib/rack/cors.rb:102
c:0073 p:0028 s:0527 e:000526 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/rack-2.2.17/lib/rack/tempfile_reaper.rb:15
c:0072 p:0007 s:0518 e:000517 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/rack-2.2.17/lib/rack/etag.rb:27
c:0071 p:0034 s:0507 e:000506 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/rack-2.2.17/lib/rack/conditional_get.rb:40
c:0070 p:0007 s:0498 e:000497 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/rack-2.2.17/lib/rack/head.rb:12
c:0069 p:0007 s:0490 e:000489 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/action_dispatch/http/permissions_policy.rb:36
c:0068 p:0007 s:0480 e:000479 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/action_dispatch/http/content_security_policy.rb:36
c:0067 p:0088 s:0466 e:000465 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/read_only/controller.rb:50
c:0066 p:0011 s:0462 e:000461 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/read_only.rb:18
c:0065 p:0007 s:0457 e:000456 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/unauthenticated_session_expiry.rb:18
c:0064 p:0026 s:0449 e:000448 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/rack-2.2.17/lib/rack/session/abstract/id.rb:266
c:0063 p:0005 s:0438 e:000437 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/rack-2.2.17/lib/rack/session/abstract/id.rb:260
c:0062 p:0007 s:0433 e:000432 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/secure_headers.rb:11
c:0061 p:0015 s:0425 e:000424 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/action_dispatch/middleware/cookies.rb:689
c:0060 p:0007 s:0417 e:000416 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/same_site_cookies.rb:27
c:0059 p:0008 s:0406 e:000405 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/action_dispatch/middleware/callbacks.rb:29
c:0058 p:0027 s:0403 e:000402 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/callbacks.rb:101
c:0057 p:0009 s:0393 e:000392 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/action_dispatch/middleware/callbacks.rb:28
c:0056 p:0021 s:0386 e:000385 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/sentry-rails-5.23.0/lib/sentry/rails/rescued_exception_interceptor.rb:14
c:0055 p:0007 s:0380 e:000379 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/action_dispatch/middleware/debug_exceptions.rb:29
c:0054 p:0050 s:0367 e:000366 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/path_traversal_check.rb:40
c:0053 p:0023 s:0360 e:000359 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/handle_malformed_strings.rb:21
c:0052 p:0066 s:0355 e:000354 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/sentry-ruby-5.23.0/lib/sentry/rack/capture_exceptions.rb:30
c:0051 p:0020 s:0348 e:000347 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/sentry-ruby-5.23.0/lib/sentry/hub.rb:299
c:0050 p:0017 s:0343 e:000342 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/sentry-ruby-5.23.0/lib/sentry-ruby.rb:428
c:0049 p:0006 s:0338 e:000337 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/sentry-ruby-5.23.0/lib/sentry/rack/capture_exceptions.rb:21
c:0048 p:0009 s:0334 e:000333 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/sentry-ruby-5.23.0/lib/sentry/hub.rb:89
c:0047 p:0017 s:0329 e:000328 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/sentry-ruby-5.23.0/lib/sentry-ruby.rb:408
c:0046 p:0024 s:0324 e:000323 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/sentry-ruby-5.23.0/lib/sentry/rack/capture_exceptions.rb:20
c:0045 p:0007 s:0319 e:000318 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/action_dispatch/middleware/show_exceptions.rb:31
c:0044 p:0019 s:0310 e:000309 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/basic_health_check.rb:25
c:0043 p:0013 s:0304 e:000303 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/lograge-0.11.2/lib/lograge/rails_ext/rack/logger.rb:15
c:0042 p:0007 s:0298 e:000297 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/railties-7.1.5.1/lib/rails/rack/logger.rb:24
c:0041 p:0003 s:0295 e:000294 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/tagged_logging.rb:139
c:0040 p:0014 s:0292 e:000291 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/tagged_logging.rb:39
c:0039 p:0015 s:0286 e:000285 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/tagged_logging.rb:139
c:0038 p:0072 s:0280 e:000279 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/activesupport-7.1.5.1/lib/active_support/broadcast_logger.rb:241
c:0037 p:0030 s:0271 e:000270 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/railties-7.1.5.1/lib/rails/rack/logger.rb:24
c:0036 p:0034 s:0265 e:000264 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/action_dispatch/middleware/remote_ip.rb:92
c:0035 p:0007 s:0259 e:000258 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/handle_ip_spoof_attack_error.rb:25
c:0034 p:0027 s:0253 e:000252 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/request_context.rb:15
c:0033 p:0024 s:0247 e:000246 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/webhook_recursion_detection.rb:15
c:0032 p:0012 s:0241 e:000240 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/request_store-1.7.0/lib/request_store/middleware.rb:19
c:0031 p:0057 s:0232 e:000231 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/rack-2.2.17/lib/rack/method_override.rb:24
c:0030 p:0013 s:0226 e:000225 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/rack-2.2.17/lib/rack/runtime.rb:22
c:0029 p:0008 s:0216 e:000215 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/rack-timeout-0.7.0/lib/rack/timeout/core.rb:154
c:0028 p:0048 s:0212 E:001230 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/rack-timeout-0.7.0/lib/rack/timeout/support/timeout.rb:19
c:0027 p:0313 s:0204 E:002068 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/rack-timeout-0.7.0/lib/rack/timeout/core.rb:153
c:0026 p:0019 s:0187 e:000186 METHOD /opt/gitlab/embedded/service/gitlab-rails/config/initializers/fix_local_cache_middleware.rb:11
c:0025 p:0070 s:0180 e:000179 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/compressed_json.rb:44
c:0024 p:0016 s:0174 e:000173 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/action_dispatch/middleware/executor.rb:14
c:0023 p:0016 s:0165 e:000164 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/rack_multipart_tempfile_factory.rb:19
c:0022 p:0050 s:0160 e:000159 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/metrics/requests_rack_middleware.rb:83
c:0021 p:0007 s:0147 e:000146 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/gitlab-labkit-0.39.0/lib/labkit/middleware/rack.rb:22
c:0020 p:0015 s:0140 e:000139 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/gitlab-labkit-0.39.0/lib/labkit/context.rb:35
c:0019 p:0014 s:0134 e:000133 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/gitlab-labkit-0.39.0/lib/labkit/middleware/rack.rb:21
c:0018 p:0007 s:0129 e:000128 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/rack-2.2.17/lib/rack/sendfile.rb:110
c:0017 p:0032 s:0117 e:000116 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/actionpack-7.1.5.1/lib/action_dispatch/middleware/request_id.rb:28
c:0016 p:0026 s:0111 e:000110 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/sidekiq_web_static.rb:20
c:0015 p:0016 s:0106 e:000105 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/railties-7.1.5.1/lib/rails/engine.rb:536 [FINISH]
c:0014 p:---- s:0100 e:000099 CFUNC  :public_send
c:0013 p:0031 s:0094 e:000093 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/railties-7.1.5.1/lib/rails/railtie.rb:226
c:0012 p:0007 s:0087 e:000086 METHOD /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/release_env.rb:12
c:0011 p:0118 s:0082 e:000081 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/rack-2.2.17/lib/rack/urlmap.rb:74 [FINISH]
c:0010 p:---- s:0073 e:000072 CFUNC  :each
c:0009 p:0089 s:0069 e:000068 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/rack-2.2.17/lib/rack/urlmap.rb:58
c:0008 p:0017 s:0057 e:000056 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/puma-6.6.0/lib/puma/configuration.rb:279
c:0007 p:0007 s:0052 e:000051 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/puma-6.6.0/lib/puma/request.rb:99
c:0006 p:0015 s:0049 e:000048 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/puma-6.6.0/lib/puma/thread_pool.rb:390
c:0005 p:0353 s:0044 e:000043 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/puma-6.6.0/lib/puma/request.rb:98
c:0004 p:0093 s:0029 e:000028 METHOD /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/puma-6.6.0/lib/puma/server.rb:472
c:0003 p:0005 s:0018 e:000017 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/puma-6.6.0/lib/puma/server.rb:254
c:0002 p:0071 s:0014 e:000013 BLOCK  /opt/gitlab/embedded/lib/ruby/gems/3.2.0/gems/puma-6.6.0/lib/puma/thread_pool.rb:167 [FINISH]
c:0001 p:---- s:0003 e:000002 DUMMY  [FINISH]

Output of checks

This bug affects all current versions of GitLab, including GitLab.com.

Results of GitLab environment info

Expand for output related to GitLab environment info
System information
System:		
Current User:	git
Using RVM:	no
Ruby Version:	3.2.5
Gem Version:	3.6.9
Bundler Version:2.6.5
Rake Version:	13.0.6
Redis Version:	7.2.9
Sidekiq Version:7.3.9
Go Version:	unknown

GitLab information
Version:	18.2.0
Revision:	95351f08aae
Directory:	/opt/gitlab/embedded/service/gitlab-rails
DB Adapter:	PostgreSQL
DB Version:	16.8
URL:		http://gitlab.example.com
HTTP Clone URL:	http://gitlab.example.com/some-group/some-project.git
SSH Clone URL:	git@gitlab.example.com:some-group/some-project.git
Using LDAP:	no
Using Omniauth:	yes
Omniauth Providers: 

GitLab Shell
Version:	14.43.0
Repository storages:
- default: 	unix:/var/opt/gitlab/gitaly/gitaly.socket
GitLab Shell path:		/opt/gitlab/embedded/service/gitlab-shell

Gitaly
- default Address: 	unix:/var/opt/gitlab/gitaly/gitaly.socket
- default Version: 	18.2.0
- default Git Version: 	2.50.1.gl1

Results of GitLab application Check

Expand for output related to the GitLab application check
Checking GitLab subtasks ...

Checking GitLab Shell ...

GitLab Shell: ... GitLab Shell version >= 14.43.0 ? ... OK (14.43.0) Running /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell-check Internal API available: OK Redis available via internal API: OK gitlab-shell self-check successful

Checking GitLab Shell ... Finished

Checking Gitaly ...

Gitaly: ... default ... OK

Checking Gitaly ... Finished

Checking Sidekiq ...

Sidekiq: ... Running? ... yes Number of Sidekiq processes (cluster/worker) ... 1/1

Checking Sidekiq ... Finished

Checking Incoming Email ...

Incoming Email: ... Reply by email is disabled in config/gitlab.yml

Checking Incoming Email ... Finished

Checking LDAP ...

LDAP: ... LDAP is disabled in config/gitlab.yml

Checking LDAP ... Finished

Checking GitLab App ...

Database config exists? ... yes Tables are truncated? ... skipped All migrations up? ... yes Database contains orphaned GroupMembers? ... no GitLab config exists? ... yes GitLab config up to date? ... yes Cable config exists? ... yes Resque config exists? ... yes Log directory writable? ... yes Tmp directory writable? ... yes Uploads directory exists? ... yes Uploads directory has correct permissions? ... yes Uploads directory tmp has correct permissions? ... skipped (no tmp uploads folder yet) Systemd unit files or init script exist? ... skipped (omnibus-gitlab has neither init script nor systemd units) Systemd unit files or init script up-to-date? ... skipped (omnibus-gitlab has neither init script nor systemd units) Projects have namespace: ... can't check, you have no projects Redis version >= 6.2.14? ... yes Ruby version >= 3.0.6 ? ... yes (3.2.5) Git user has default SSH configuration? ... yes Active users: ... 1 Is authorized keys file accessible? ... yes GitLab configured to store new projects in hashed storage? ... yes All projects are in hashed storage? ... yes

Checking GitLab App ... Finished

Checking GitLab subtasks ... Finished

Possible fixes

Properly implement public key validation according to X9.62 Section 5.2.2. It seems that this is already done partially, because keys violating other constraints are already being rejected by Gitlab.

Input: A valid set of elliptic curve domain parameters, and an associated public key Q.
Output: The message “valid” if Q is a valid public key for the given set of elliptic curve domain parameters; otherwise the message “invalid”.

1. Verify that Q is not the point at infinity.
2. Verify that x_Q and y_Q are elements in the field F_q, where x_Q and y_Q are the x and y coordinates of Q,
respectively. (That is, verify that x_Q and y_Q are integers in the interval [0, p-1] in the case that q = p is an
odd prime, or that x_Q and y_Q are bit strings of length m bits in the case that q = 2m.)
3. If q = p is an odd prime, verify that y_Q^2 ≡ x_Q^3 + ax_Q + b (mod p). If q = 2m, verify that y_Q^2 + x_Q*y_Q = x_Q^3 + ax_Q^2 + b in F_2m.
4. Verify that nQ = point at infinity. (See Annex D.3.2.)
5. If any one of the above verifications fail, then output “invalid”. If all the verifications pass, then output
“valid”.

cc @gitlab-com/gl-security/appsec