Pushing composer packages results in 500 on non-standard tags

Summary

I'm trying to use the newly available package registry for PHP. When trying make the API call to create the package with the tag "test", the API returns an error 500.

According to the production log, it might have something to do with Gitlab not being able to verify the CSRF Token, but this does not show up when using a normal tag.

Steps to reproduce

Create a project with a composer.json and execute the API call to create the package (don't forget to create a tag, I chose test and 1.0.0):

curl --tag test 'https://__token__:<private_access_token>@gitlab.domain.tld/api/v4/project/<project_id>/packages/composer/'
{"message":"500 Internal Server Error"}
curl --tag 1.0.0 'https://__token__:<private_access_token>@gitlab.domain.tld/api/v4/project/<project_id>/packages/composer/'
{"message":"201 Created"}

This works fine with tags like "1.0" or "v1.0" but breaks with anything else.

This behaviour might be intended, but then I guess the error message should tell the developer what went wrong.

What is the current bug behavior?

Instead of creating a package, the api returns an error 500.

What is the expected correct behavior?

The package is created in my project with the tag "test".

Relevant logs

gitlab-rails/production.log
Started POST "/api/v4/projects/1533/packages/composer" for 82.220.9.178 at 2020-08-27 16:56:06 +0200
Processing by Gitlab::RequestForgeryProtection::Controller#index as */*
  Parameters: {"tag"=>"test"}
Can't verify CSRF token authenticity.
This CSRF token verification failure is handled internally by `GitLab::RequestForgeryProtection`
Unlike the logs may suggest, this does not result in an actual 422 response to the user
For API requests, the only effect is that `current_user` will be `nil` for the duration of the request
Completed 422 Unprocessable Entity in 2ms (ActiveRecord: 0.0ms | Elasticsearch: 0.0ms | Allocations: 213)

NoMethodError (undefined method captures' for nil:NilClass): /opt/gitlab/embedded/service/gitlab-rails/app/services/packages/composer/version_parser_service.rb:12:in execute' /opt/gitlab/embedded/service/gitlab-rails/app/services/packages/composer/create_package_service.rb:53:in package_version' /opt/gitlab/embedded/service/gitlab-rails/app/services/packages/composer/create_package_service.rb:27:in created_package' /opt/gitlab/embedded/service/gitlab-rails/app/services/packages/composer/create_package_service.rb:14:in block in execute' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/database_statements.rb:280:in block in transaction' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/transaction.rb:280:in block in within_new_transaction' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:26:in block (2 levels) in synchronize' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in handle_interrupt' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in block in synchronize' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in handle_interrupt' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in synchronize' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/transaction.rb:278:in within_new_transaction' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/database_statements.rb:280:in transaction' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/transactions.rb:212:in transaction' /opt/gitlab/embedded/service/gitlab-rails/app/services/packages/composer/create_package_service.rb:12:in execute' /opt/gitlab/embedded/service/gitlab-rails/lib/api/composer_packages.rb:130:in block (3 levels) in <class:ComposerPackages>' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/endpoint.rb:59:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/endpoint.rb:59:in block (2 levels) in generate_api_method' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/notifications.rb:182:in instrument' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/endpoint.rb:58:in block in generate_api_method' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/endpoint.rb:341:in execute' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/endpoint.rb:267:in block in run' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/notifications.rb:180:in block in instrument' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/notifications/instrumenter.rb:24:in instrument' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/notifications.rb:180:in instrument' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/endpoint.rb:247:in run' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/endpoint.rb:322:in block in build_stack' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/middleware/base.rb:35:in call!' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/middleware/base.rb:28:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/middleware/base.rb:35:in call!' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/middleware/base.rb:28:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/middleware/base.rb:35:in call!' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/middleware/base.rb:28:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/rack-oauth2-1.9.3/lib/rack/oauth2/server/resource.rb:20:in _call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/rack-oauth2-1.9.3/lib/rack/oauth2/server/resource/bearer.rb:8:in _call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/rack-oauth2-1.9.3/lib/rack/oauth2/server/abstract/handler.rb:17:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/middleware/error.rb:39:in block in call!' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/middleware/error.rb:38:in catch' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/middleware/error.rb:38:in call!' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/middleware/base.rb:28:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape_logging-1.8.3/lib/grape_logging/middleware/request_logger.rb:60:in block in call!' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape_logging-1.8.3/lib/grape_logging/middleware/request_logger.rb:58:in catch' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape_logging-1.8.3/lib/grape_logging/middleware/request_logger.rb:58:in call!' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/middleware/base.rb:28:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/rack-2.0.9/lib/rack/head.rb:12:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/endpoint.rb:231:in call!' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/endpoint.rb:225:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/router/route.rb:58:in exec' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/router.rb:116:in process_route' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/router.rb:72:in block in identity' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/router.rb:91:in transaction' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/router.rb:70:in identity' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/router.rb:55:in block in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/router.rb:132:in with_optimization' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/router.rb:54:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/api/instance.rb:167:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/api/instance.rb:71:in call!' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/grape-1.4.0/lib/grape/api/instance.rb:66:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/actionpack-6.0.3.1/lib/action_dispatch/routing/mapper.rb:19:in block in class:Constraints' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/actionpack-6.0.3.1/lib/action_dispatch/routing/mapper.rb:48:in serve' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/actionpack-6.0.3.1/lib/action_dispatch/journey/router.rb:49:in block in serve' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/actionpack-6.0.3.1/lib/action_dispatch/journey/router.rb:32:in each' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/actionpack-6.0.3.1/lib/action_dispatch/journey/router.rb:32:in serve' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/actionpack-6.0.3.1/lib/action_dispatch/routing/route_set.rb:834:in call' /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/request_profiler/middleware.rb:17:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/gitlab-labkit-0.12.1/lib/labkit/middleware/rack.rb:19:in block in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/gitlab-labkit-0.12.1/lib/labkit/context.rb:32:in with_context' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/gitlab-labkit-0.12.1/lib/labkit/middleware/rack.rb:18:in call' /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/go.rb:20:in call' /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/etag_caching/middleware.rb:13:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/batch-loader-1.4.0/lib/batch_loader/middleware.rb:11:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/rack-attack-6.3.0/lib/rack/attack.rb:97:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/apollo_upload_server-2.0.0.beta.3/lib/apollo_upload_server/middleware.rb:20:in call' /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/multipart.rb:140:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/rack-attack-6.3.0/lib/rack/attack.rb:111:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/warden-1.2.8/lib/warden/manager.rb:36:in block in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/warden-1.2.8/lib/warden/manager.rb:34:in catch' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/warden-1.2.8/lib/warden/manager.rb:34:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/rack-cors-1.0.6/lib/rack/cors.rb:98:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/rack-2.0.9/lib/rack/tempfile_reaper.rb:15:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/rack-2.0.9/lib/rack/etag.rb:25:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/rack-2.0.9/lib/rack/conditional_get.rb:38:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/rack-2.0.9/lib/rack/head.rb:12:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/actionpack-6.0.3.1/lib/action_dispatch/http/content_security_policy.rb:18:in call' /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/read_only/controller.rb:51:in call' /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/read_only.rb:18:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/rack-2.0.9/lib/rack/session/abstract/id.rb:259:in context' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/rack-2.0.9/lib/rack/session/abstract/id.rb:253:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/actionpack-6.0.3.1/lib/action_dispatch/middleware/cookies.rb:648:in call' /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/same_site_cookies.rb:27:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/actionpack-6.0.3.1/lib/action_dispatch/middleware/callbacks.rb:27:in block in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/callbacks.rb:101:in run_callbacks' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/actionpack-6.0.3.1/lib/action_dispatch/middleware/callbacks.rb:26:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/actionpack-6.0.3.1/lib/action_dispatch/middleware/actionable_exceptions.rb:17:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/actionpack-6.0.3.1/lib/action_dispatch/middleware/debug_exceptions.rb:32:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/actionpack-6.0.3.1/lib/action_dispatch/middleware/show_exceptions.rb:33:in call' /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/basic_health_check.rb:25:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/railties-6.0.3.1/lib/rails/rack/logger.rb:37:in call_app' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/railties-6.0.3.1/lib/rails/rack/logger.rb:26:in block in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/tagged_logging.rb:80:in block in tagged' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/tagged_logging.rb:28:in tagged' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.1/lib/active_support/tagged_logging.rb:80:in tagged' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/railties-6.0.3.1/lib/rails/rack/logger.rb:26:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/actionpack-6.0.3.1/lib/action_dispatch/middleware/remote_ip.rb:81:in call' /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/handle_ip_spoof_attack_error.rb:25:in call' /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/request_context.rb:23:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/request_store-1.5.0/lib/request_store/middleware.rb:19:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/actionpack-6.0.3.1/lib/action_dispatch/middleware/request_id.rb:27:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/rack-2.0.9/lib/rack/method_override.rb:22:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/rack-2.0.9/lib/rack/runtime.rb:22:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/rack-timeout-0.5.2/lib/rack/timeout/core.rb:123:in block in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/rack-timeout-0.5.2/lib/rack/timeout/support/timeout.rb:19:in timeout' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/rack-timeout-0.5.2/lib/rack/timeout/core.rb:122:in call' /opt/gitlab/embedded/service/gitlab-rails/config/initializers/fix_local_cache_middleware.rb:9:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/actionpack-6.0.3.1/lib/action_dispatch/middleware/executor.rb:14:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/rack-2.0.9/lib/rack/sendfile.rb:111:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/actionpack-6.0.3.1/lib/action_dispatch/middleware/host_authorization.rb:76:in call' /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/metrics/requests_rack_middleware.rb:60:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/sentry-raven-2.9.0/lib/raven/integrations/rack.rb:51:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/railties-6.0.3.1/lib/rails/engine.rb:527:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/railties-6.0.3.1/lib/rails/railtie.rb:190:in public_send' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/railties-6.0.3.1/lib/rails/railtie.rb:190:in method_missing' /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/middleware/release_env.rb:12:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/rack-2.0.9/lib/rack/urlmap.rb:68:in block in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/rack-2.0.9/lib/rack/urlmap.rb:53:in each' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/rack-2.0.9/lib/rack/urlmap.rb:53:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/gitlab-puma-4.3.3.gitlab.2/lib/puma/configuration.rb:228:in call' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/gitlab-puma-4.3.3.gitlab.2/lib/puma/server.rb:691:in handle_request' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/gitlab-puma-4.3.3.gitlab.2/lib/puma/server.rb:481:in process_client' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/gitlab-puma-4.3.3.gitlab.2/lib/puma/server.rb:335:in block in run' /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/gitlab-puma-4.3.3.gitlab.2/lib/puma/thread_pool.rb:138:in block in spawn_thread'

And this is what happens when calling the API with a "normal" tag.

Started POST "/api/v4/projects/1533/packages/composer" for 82.220.9.178 at 2020-08-27 17:16:35 +0200

Details of package version

Provide the package version installation details
dpkg-query -l "gitlab-*"
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name                   Version          Architecture     Description
+++-======================-================-================-==================================================
ii  gitlab-ce              13.3.0-ce.1      amd64            GitLab Community Edition (including NGINX, Postgre
un  gitlab-ee                                    (no description available)