From 95fd2417d4024120a4f9533330e8798194ca43e3 Mon Sep 17 00:00:00 2001 From: mao chao Date: Fri, 19 Apr 2024 11:11:35 +0800 Subject: [PATCH 1/6] Add skip nuget package setting --- app/helpers/application_settings_helper.rb | 1 + app/models/application_setting.rb | 6 ++ .../application_setting_implementation.rb | 3 +- app/models/packages/nuget/metadatum.rb | 30 ++++++- .../application_setting_package_registry.json | 12 +++ .../_nuget_skip_metadata_url_validation.haml | 15 ++++ .../_package_registry.html.haml | 2 + ...package_registry_in_application_setting.rb | 17 ++++ db/schema_migrations/20240318014850 | 1 + db/structure.sql | 2 + doc/api/settings.md | 1 + doc/development/packages/settings.md | 1 + .../_ee_package_registry.haml | 15 +++- ee/spec/features/admin/admin_settings_spec.rb | 12 +-- locale/gitlab.pot | 12 +++ spec/features/admin/admin_settings_spec.rb | 88 +++++++++++-------- spec/models/application_setting_spec.rb | 2 + spec/models/packages/nuget/metadatum_spec.rb | 9 ++ .../_package_registry.html.haml_spec.rb | 19 ++++ 19 files changed, 201 insertions(+), 47 deletions(-) create mode 100644 app/validators/json_schemas/application_setting_package_registry.json create mode 100644 app/views/admin/application_settings/_nuget_skip_metadata_url_validation.haml create mode 100644 db/migrate/20240318014850_add_package_registry_in_application_setting.rb create mode 100644 db/schema_migrations/20240318014850 diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index 177adb36cd44a3..98261316e00e1b 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -530,6 +530,7 @@ def visible_attributes else settings << :deactivate_dormant_users settings << :deactivate_dormant_users_period + settings << :nuget_skip_metadata_url_validation end end end diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 0eb1a79dfe14ce..ce00cf0055aab2 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -32,6 +32,8 @@ class ApplicationSetting < MainClusterwide::ApplicationRecord # matches the size set in the database constraint DEFAULT_BRANCH_PROTECTIONS_DEFAULT_MAX_SIZE = 1.kilobyte + PACKAGE_REGISTRY_SETTINGS = [:nuget_skip_metadata_url_validation].freeze + enum whats_new_variant: { all_tiers: 0, current_tier: 1, disabled: 2 }, _prefix: true enum email_confirmation_setting: { off: 0, soft: 1, hard: 2 }, _prefix: true @@ -621,6 +623,10 @@ def self.kroki_formats_attributes validates :rate_limits, json_schema: { filename: "application_setting_rate_limits" } + jsonb_accessor :package_registry, nuget_skip_metadata_url_validation: [:boolean, { default: false }] + + validates :package_registry, json_schema: { filename: 'application_setting_package_registry' } + validates :search_rate_limit_allowlist, length: { maximum: 100, message: N_('is too long (maximum is 100 entries)') }, allow_nil: false diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb index e715bc86693027..ff050b05a1b759 100644 --- a/app/models/application_setting_implementation.rb +++ b/app/models/application_setting_implementation.rb @@ -285,7 +285,8 @@ def defaults # rubocop:disable Metrics/AbcSize security_approval_policies_limit: 5, downstream_pipeline_trigger_limit_per_project_user_sha: 0, asciidoc_max_includes: 32, - use_clickhouse_for_analytics: false + use_clickhouse_for_analytics: false, + nuget_skip_metadata_url_validation: false }.tap do |hsh| hsh.merge!(non_production_defaults) unless Rails.env.production? end diff --git a/app/models/packages/nuget/metadatum.rb b/app/models/packages/nuget/metadatum.rb index 1025af0fd24a60..100f9f2d83f3be 100644 --- a/app/models/packages/nuget/metadatum.rb +++ b/app/models/packages/nuget/metadatum.rb @@ -10,9 +10,17 @@ class Packages::Nuget::Metadatum < ApplicationRecord belongs_to :package, -> { where(package_type: :nuget) }, inverse_of: :nuget_metadatum validates :package, presence: true - validates :license_url, public_url: { allow_blank: true }, length: { maximum: MAX_URL_LENGTH } - validates :project_url, public_url: { allow_blank: true }, length: { maximum: MAX_URL_LENGTH } - validates :icon_url, public_url: { allow_blank: true }, length: { maximum: MAX_URL_LENGTH } + validate :ensure_valid_urls + with_options if: :url_validation_enabled?, public_url: { allow_blank: true } do + validates :license_url + validates :project_url + validates :icon_url + end + with_options length: { maximum: MAX_URL_LENGTH } do + validates :license_url + validates :project_url + validates :icon_url + end validates :authors, presence: true, length: { maximum: MAX_AUTHORS_LENGTH } validates :description, presence: true, length: { maximum: MAX_DESCRIPTION_LENGTH } validates :normalized_version, presence: true @@ -25,9 +33,25 @@ class Packages::Nuget::Metadatum < ApplicationRecord private + def url_validation_enabled? + !Gitlab::CurrentSettings.current_application_settings.nuget_skip_metadata_url_validation + end + def ensure_nuget_package_type return if package&.nuget? errors.add(:base, _('Package type must be NuGet')) end + + def ensure_valid_urls + %w[license_url project_url icon_url].each do |field| + value = attributes[field] + + next if value.blank? + + unless Gitlab::UrlSanitizer.valid?(value, allowed_schemes: %w[http https]) + errors.add(field, _('is an invalid URL')) + end + end + end end diff --git a/app/validators/json_schemas/application_setting_package_registry.json b/app/validators/json_schemas/application_setting_package_registry.json new file mode 100644 index 00000000000000..4316041a1e45c4 --- /dev/null +++ b/app/validators/json_schemas/application_setting_package_registry.json @@ -0,0 +1,12 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Application Package Registry related settings", + "type": "object", + "properties": { + "nuget_skip_metadata_url_validation": { + "type": "boolean", + "description": "Indicates whether skips validation of NuGet package metadata URLs" + } + }, + "additionalProperties": false +} diff --git a/app/views/admin/application_settings/_nuget_skip_metadata_url_validation.haml b/app/views/admin/application_settings/_nuget_skip_metadata_url_validation.haml new file mode 100644 index 00000000000000..466b0215b8f06e --- /dev/null +++ b/app/views/admin/application_settings/_nuget_skip_metadata_url_validation.haml @@ -0,0 +1,15 @@ +%h5 + = s_('PackageRegistry|Skip NuGet package metadata url validations') +%p + = s_('PackageRegistry|By default GitLab NuGet package service will validate the %{code_open}projectUrl%{code_close}, %{code_open}iconUrl%{code_close} and %{code_open}licenseUrl%{code_close} in the package metadata. In the environment with restricted network access or air-gapped it will block the Nuget package upload as those could not be resolved. Check the option below to skip the validation.').html_safe % { code_open: ''.html_safe, code_close: ''.html_safe } +%p + = s_('PackageRegistry|Please consider manually validating these URLs to prevent malicious packages from being uploaded to GitLab Nuget package registry. Enabling and disabling this option can lead to invalid records in the Package Registry that cannot be updated.') += gitlab_ui_form_for @application_setting, url: ci_cd_admin_application_settings_path(anchor: 'js-package-settings'), html: { class: 'fieldset-form' }, data: { testid: 'skip-nuget-package-metadata-url-validation-form' } do |f| + = form_errors(@application_setting) + + %fieldset + .form-group + = f.gitlab_ui_checkbox_component :nuget_skip_metadata_url_validation, + s_('PackageRegistry|Skip NuGet package metadata url validations') + + = f.submit _('Save changes'), pajamas_button: true diff --git a/app/views/admin/application_settings/_package_registry.html.haml b/app/views/admin/application_settings/_package_registry.html.haml index 23251c8f5c93a9..b370891b169c00 100644 --- a/app/views/admin/application_settings/_package_registry.html.haml +++ b/app/views/admin/application_settings/_package_registry.html.haml @@ -10,6 +10,8 @@ .settings-content = render_if_exists 'admin/application_settings/ee_package_registry' + = render 'admin/application_settings/nuget_skip_metadata_url_validation' unless Gitlab.ee? + .gl-mt-7 %h4 diff --git a/db/migrate/20240318014850_add_package_registry_in_application_setting.rb b/db/migrate/20240318014850_add_package_registry_in_application_setting.rb new file mode 100644 index 00000000000000..cad4d4a22556ff --- /dev/null +++ b/db/migrate/20240318014850_add_package_registry_in_application_setting.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class AddPackageRegistryInApplicationSetting < Gitlab::Database::Migration[2.2] + milestone '16.11' + disable_ddl_transaction! + + CONSTRAINT_NAME = 'check_application_settings_package_registry_is_hash' + + def up + add_column :application_settings, :package_registry, :jsonb, default: {}, null: false + add_check_constraint(:application_settings, "(jsonb_typeof(package_registry) = 'object')", CONSTRAINT_NAME) + end + + def down + remove_column :application_settings, :package_registry + end +end diff --git a/db/schema_migrations/20240318014850 b/db/schema_migrations/20240318014850 new file mode 100644 index 00000000000000..c91e5497651275 --- /dev/null +++ b/db/schema_migrations/20240318014850 @@ -0,0 +1 @@ +28a65d98279742cbd77415037f7c6c2f96015508f38a81ed8b76a28aeb9b2df1 \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 19a29fe7a4ed49..dba8566cca9ceb 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -4415,6 +4415,7 @@ CREATE TABLE application_settings ( include_optional_metrics_in_service_ping boolean DEFAULT true NOT NULL, zoekt_settings jsonb DEFAULT '{}'::jsonb NOT NULL, service_ping_settings jsonb DEFAULT '{}'::jsonb NOT NULL, + package_registry jsonb DEFAULT '{}'::jsonb NOT NULL, rate_limits_unauthenticated_git_http jsonb DEFAULT '{}'::jsonb NOT NULL, CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)), CONSTRAINT app_settings_container_registry_pre_import_tags_rate_positive CHECK ((container_registry_pre_import_tags_rate >= (0)::numeric)), @@ -4467,6 +4468,7 @@ CREATE TABLE application_settings ( CONSTRAINT check_app_settings_namespace_storage_forks_cost_factor_range CHECK (((namespace_storage_forks_cost_factor >= (0)::double precision) AND (namespace_storage_forks_cost_factor <= (1)::double precision))), CONSTRAINT check_app_settings_sentry_clientside_traces_sample_rate_range CHECK (((sentry_clientside_traces_sample_rate >= (0)::double precision) AND (sentry_clientside_traces_sample_rate <= (1)::double precision))), CONSTRAINT check_application_settings_clickhouse_is_hash CHECK ((jsonb_typeof(clickhouse) = 'object'::text)), + CONSTRAINT check_application_settings_package_registry_is_hash CHECK ((jsonb_typeof(package_registry) = 'object'::text)), CONSTRAINT check_application_settings_rate_limits_is_hash CHECK ((jsonb_typeof(rate_limits) = 'object'::text)), CONSTRAINT check_application_settings_rate_limits_unauth_git_http_is_hash CHECK ((jsonb_typeof(rate_limits_unauthenticated_git_http) = 'object'::text)), CONSTRAINT check_application_settings_service_ping_settings_is_hash CHECK ((jsonb_typeof(service_ping_settings) = 'object'::text)), diff --git a/doc/api/settings.md b/doc/api/settings.md index e6a6c892972190..76dda0d756b31f 100644 --- a/doc/api/settings.md +++ b/doc/api/settings.md @@ -664,6 +664,7 @@ listed in the descriptions of the relevant settings. | `asciidoc_max_includes` | integer | no | Maximum limit of AsciiDoc include directives being processed in any one document. Default: 32. Maximum: 64. | | `duo_features_enabled` | boolean | no | Indicates whether GitLab Duo features are enabled for this instance. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144931) in GitLab 16.10. Self-managed, Premium and Ultimate only. | | `lock_duo_features_enabled` | boolean | no | Indicates whether the GitLab Duo features enabled setting is enforced for all subgroups. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144931) in GitLab 16.10. Self-managed, Premium and Ultimate only. | +| `nuget_skip_metadata_url_validation` | boolean | no | Indicates whether skips validation of NuGet package metadata URLs. | ### Configure inactive project deletion diff --git a/doc/development/packages/settings.md b/doc/development/packages/settings.md index 491d681486f889..47cb0cc0a127ed 100644 --- a/doc/development/packages/settings.md +++ b/doc/development/packages/settings.md @@ -14,6 +14,7 @@ This page includes an exhaustive list of settings related to and maintained by t | Setting | Table | Description | | ------- | ----- | -----------| +| `nuget_skip_metadata_url_validation` | `application_settings` | Enables or disables skips validation of NuGet package metadata URLs. | | `npm_package_requests_forwarding` | `application_settings` | Enables or disables npm package forwarding at the instance level. | | `pypi_package_requests_forwarding` | `application_settings` | Enables or disables PyPI package forwarding at the instance level. | | `packages_cleanup_package_file_worker_capacity` | `application_settings` | Number of concurrent workers allowed for package file cleanup. | diff --git a/ee/app/views/admin/application_settings/_ee_package_registry.haml b/ee/app/views/admin/application_settings/_ee_package_registry.haml index f29400642e58e5..763cc1022f67e3 100644 --- a/ee/app/views/admin/application_settings/_ee_package_registry.haml +++ b/ee/app/views/admin/application_settings/_ee_package_registry.haml @@ -5,7 +5,7 @@ %p - docs_link = link_to('', help_page_path('user/packages/package_registry/supported_functionality', { anchor: 'deleting-packages' })) = safe_format(s_('PackageRegistry|There are security risks if packages are deleted while request forwarding is enabled. %{docs_link_start}What are the risks?%{docs_link_end}'), tag_pair(docs_link, :docs_link_start, :docs_link_end)) -= gitlab_ui_form_for @application_setting, url: ci_cd_admin_application_settings_path(anchor: 'js-package-settings'), html: { class: 'fieldset-form' } do |f| += gitlab_ui_form_for @application_setting, url: ci_cd_admin_application_settings_path(anchor: 'js-package-settings'), html: { class: 'fieldset-form' }, data: { testid: 'forward-package-requests-form' } do |f| = form_errors(@application_setting) %fieldset @@ -28,4 +28,17 @@ = f.gitlab_ui_checkbox_component :lock_maven_package_requests_forwarding, s_('PackageRegistry|Enforce %{package_type} setting for all subgroups') % { package_type: 'Maven' } + - unless Gitlab.com? + %h5 + = s_('PackageRegistry|Skip NuGet package metadata url validations') + %p + = s_('PackageRegistry|By default GitLab NuGet package service will validate the %{code_open}projectUrl%{code_close}, %{code_open}iconUrl%{code_close} and %{code_open}licenseUrl%{code_close} in the package metadata. In the environment with restricted network access or air-gapped it will block the Nuget package upload as those could not be resolved. Check the option below to skip the validation.').html_safe % { code_open: ''.html_safe, code_close: ''.html_safe } + %p + = s_('PackageRegistry|Please consider manually validating these URLs to prevent malicious packages from being uploaded to GitLab Nuget package registry. Enabling and disabling this option can lead to invalid records in the Package Registry that cannot be updated.') + + %fieldset + .form-group + = f.gitlab_ui_checkbox_component :nuget_skip_metadata_url_validation, + s_('PackageRegistry|Skip NuGet package metadata url validations') + = f.submit _('Save changes'), pajamas_button: true diff --git a/ee/spec/features/admin/admin_settings_spec.rb b/ee/spec/features/admin/admin_settings_spec.rb index db78043531a348..ba65a6da0d7a07 100644 --- a/ee/spec/features/admin/admin_settings_spec.rb +++ b/ee/spec/features/admin/admin_settings_spec.rb @@ -247,7 +247,7 @@ end it 'allows you to change the maven_forwarding setting' do - page.within('#js-package-settings') do + within_testid('forward-package-requests-form') do check 'Forward Maven package requests' click_button 'Save' end @@ -256,7 +256,7 @@ end it 'allows you to change the maven_lock setting' do - page.within('#js-package-settings') do + within_testid('forward-package-requests-form') do check 'Enforce Maven setting for all subgroups' click_button 'Save' end @@ -265,7 +265,7 @@ end it 'allows you to change the npm_forwarding setting' do - page.within('#js-package-settings') do + within_testid('forward-package-requests-form') do check 'Forward npm package requests' click_button 'Save' end @@ -274,7 +274,7 @@ end it 'allows you to change the npm_lock setting' do - page.within('#js-package-settings') do + within_testid('forward-package-requests-form') do check 'Enforce npm setting for all subgroups' click_button 'Save' end @@ -283,7 +283,7 @@ end it 'allows you to change the pypi_forwarding setting' do - page.within('#js-package-settings') do + within_testid('forward-package-requests-form') do check 'Forward PyPI package requests' click_button 'Save' end @@ -292,7 +292,7 @@ end it 'allows you to change the pypi_lock setting' do - page.within('#js-package-settings') do + within_testid('forward-package-requests-form') do check 'Enforce PyPI setting for all subgroups' click_button 'Save' end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index d8ef2caa09263e..22524fdcfa8b02 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -36347,6 +36347,9 @@ msgstr "" msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}" msgstr "" +msgid "PackageRegistry|By default GitLab NuGet package service will validate the %{code_open}projectUrl%{code_close}, %{code_open}iconUrl%{code_close} and %{code_open}licenseUrl%{code_close} in the package metadata. In the environment with restricted network access or air-gapped it will block the Nuget package upload as those could not be resolved. Check the option below to skip the validation." +msgstr "" + msgid "PackageRegistry|Composer" msgstr "" @@ -36664,6 +36667,9 @@ msgstr "" msgid "PackageRegistry|Pip Command" msgstr "" +msgid "PackageRegistry|Please consider manually validating these URLs to prevent malicious packages from being uploaded to GitLab Nuget package registry. Enabling and disabling this option can lead to invalid records in the Package Registry that cannot be updated." +msgstr "" + msgid "PackageRegistry|Processing" msgstr "" @@ -36736,6 +36742,9 @@ msgstr "" msgid "PackageRegistry|Show Yarn commands" msgstr "" +msgid "PackageRegistry|Skip NuGet package metadata url validations" +msgstr "" + msgid "PackageRegistry|Some of the selected package formats allow request forwarding. Deleting a package while request forwarding is enabled for the project can pose a security risk. Do you want to proceed with deleting the selected packages? %{docLinkStart}What are the risks?%{docLinkEnd}" msgstr "" @@ -61206,6 +61215,9 @@ msgstr "" msgid "is an invalid IP address range" msgstr "" +msgid "is an invalid URL" +msgstr "" + msgid "is blocked by" msgstr "" diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index 4869779cb5358a..aa763d0c90e175 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -27,7 +27,7 @@ click_button 'Save changes' end - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' end it 'uncheck all restricted visibility levels' do @@ -41,7 +41,7 @@ click_button 'Save changes' end - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' within_testid('restricted-visibility-levels') do expect(find_field(s_('VisibilityLevel|Public'))).not_to be_checked @@ -58,7 +58,7 @@ click_button 'Save changes' end - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' expect(current_settings.import_sources).to eq(['git']) end @@ -77,7 +77,7 @@ expect(current_settings.project_export_enabled).to be_falsey expect(current_settings.bulk_import_enabled).to be(true) - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' end it 'change Keys settings' do @@ -109,7 +109,7 @@ end expect(current_settings.gravatar_enabled).to be_falsey - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' end it 'change Maximum export size' do @@ -119,7 +119,7 @@ end expect(current_settings.max_export_size).to eq 25 - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' end it 'change Maximum import size' do @@ -129,7 +129,7 @@ end expect(current_settings.max_import_size).to eq 15 - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' end it 'change New users set to external', :js do @@ -230,7 +230,7 @@ end expect(current_settings.require_admin_approval_after_user_signup).to be_truthy - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' end end @@ -246,7 +246,7 @@ end expect(current_settings.email_confirmation_setting).to eq('hard') - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' end end end @@ -258,7 +258,7 @@ end expect(current_settings.home_page_url).to eq "https://about.gitlab.com/" - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' end it 'terms of Service', :js do @@ -288,7 +288,7 @@ click_button 'Save changes' end - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' expect(current_settings.disabled_oauth_sign_in_sources).to include('google_oauth2') page.within('.as-signin') do @@ -296,7 +296,7 @@ click_button 'Save changes' end - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' expect(current_settings.disabled_oauth_sign_in_sources).not_to include('google_oauth2') end @@ -308,7 +308,7 @@ click_button 'Save changes' end - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' expect(current_settings.disabled_oauth_sign_in_sources).to include('google_oauth2') # Remove google_oauth2 from the Omniauth strategies @@ -319,7 +319,7 @@ click_button 'Save changes' end - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' expect(current_settings.disabled_oauth_sign_in_sources).to include('google_oauth2') end @@ -329,7 +329,7 @@ click_button 'Save changes' end - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' expect(current_settings.terminal_max_session_time).to eq(15) end @@ -359,7 +359,7 @@ expect(current_settings.jira_connect_application_key).to eq('1234') expect(current_settings.jira_connect_proxy_url).to eq('https://example.com') expect(current_settings.jira_connect_public_key_storage_enabled).to eq(true) - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' end end @@ -420,7 +420,7 @@ click_button 'Save changes' end - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' expect(current_settings.hide_third_party_offers).to be true end @@ -469,7 +469,7 @@ expect(current_settings.suggest_pipeline_enabled).to be false expect(current_settings.ci_max_includes).to be 200 expect(current_settings.downstream_pipeline_trigger_limit_per_project_user_sha).to be 500 - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' end it 'changes CI/CD limits', :aggregate_failures do @@ -497,6 +497,22 @@ expect(page).to have_content 'Application limits saved successfully' end + context 'Skip NuGet package metadata url validation' do + it 'updates skip NuGet url validation' do + allow(Gitlab).to receive(:com?).and_return(false) + + visit ci_cd_admin_application_settings_path + + within_testid('forward-package-requests-form') do + check 'Skip NuGet package metadata url validations' + click_button 'Save changes' + end + + expect(current_settings.nuget_skip_metadata_url_validation).to be true + expect(page).to have_content 'Application settings saved successfully' + end + end + context 'Runner Registration' do it 'allows admins to control who has access to register runners' do visit ci_cd_admin_application_settings_path @@ -510,7 +526,7 @@ end expect(current_settings.valid_runner_registrars).to eq([]) - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' end end @@ -541,7 +557,7 @@ end expect(current_settings.public_send(setting)).to eq(400) - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' end end end @@ -558,7 +574,7 @@ end expect(current_settings.container_registry_expiration_policies_caching).to eq(!old_value) - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' end end end @@ -624,7 +640,7 @@ click_button 'Save changes' end - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' expect(current_settings.recaptcha_enabled).to be true expect(current_settings.login_recaptcha_protection_enabled).to be true expect(current_settings.unique_ips_limit_per_user).to eq(15) @@ -645,7 +661,7 @@ end expect(current_settings.prometheus_metrics_enabled?).to be true - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' end it 'change Performance bar settings' do @@ -657,7 +673,7 @@ click_on 'Save changes' end - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' expect(find_field('Allow non-administrators access to the performance bar')).to be_checked expect(find_field('Allow access to members of the following group').value).to eq group.path @@ -729,7 +745,7 @@ click_button 'Save changes' end - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' expect(current_settings.allow_local_requests_from_web_hooks_and_services).to be true expect(current_settings.allow_local_requests_from_system_hooks).to be false expect(current_settings.dns_rebinding_protection_enabled).to be false @@ -762,7 +778,7 @@ click_button 'Save changes' end - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' expect(current_settings).to have_attributes( throttle_unauthenticated_api_enabled: true, @@ -790,7 +806,7 @@ click_button 'Save changes' end - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' expect(current_settings.issues_create_limit).to eq(0) end @@ -802,7 +818,7 @@ click_button 'Save changes' end - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' expect(current_settings.pipeline_limit_per_project_user_sha).to eq(10) end @@ -815,7 +831,7 @@ click_button 'Save changes' end - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' expect(current_settings.users_get_by_id_limit).to eq(0) expect(current_settings.users_get_by_id_limit_allowlist).to eq(%w[someone someone_else]) end @@ -828,7 +844,7 @@ click_button 'Save changes' end - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' expect(current_settings.gitlab_shell_operation_limit).to eq(100) end @@ -840,7 +856,7 @@ click_button 'Save changes' end - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' expect(current_settings.projects_api_rate_limit_unauthenticated).to eq(100) end @@ -860,7 +876,7 @@ click_button 'Save changes' end - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' expect(current_settings).to have_attributes( "throttle_unauthenticated_#{fragment}_enabled" => true, @@ -903,7 +919,7 @@ click_button 'Save changes' end - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' expect(current_settings.search_rate_limit).to eq(98) expect(current_settings.search_rate_limit_unauthenticated).to eq(76) end @@ -946,7 +962,7 @@ expect(current_settings.help_page_hide_commercial_content).to be_truthy expect(current_settings.help_page_support_url).to eq new_support_url expect(current_settings.help_page_documentation_base_url).to eq new_documentation_url - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' end it 'change Pages settings' do @@ -958,7 +974,7 @@ expect(current_settings.max_pages_size).to eq 15 expect(current_settings.pages_domain_verification_enabled?).to be_truthy - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' end it 'change Real-time features settings' do @@ -968,7 +984,7 @@ end expect(current_settings.polling_interval_multiplier).to eq 5.0 - expect(page).to have_content "Application settings saved successfully" + expect(page).to have_content 'Application settings saved successfully' end it 'shows an error when validation fails' do diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index 55d78e13cc1365..fe79b36e9c987d 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -34,6 +34,7 @@ it { expect(setting.concurrent_github_import_jobs_limit).to eq(1000) } it { expect(setting.concurrent_bitbucket_import_jobs_limit).to eq(100) } it { expect(setting.concurrent_bitbucket_server_import_jobs_limit).to eq(100) } + it { expect(setting.nuget_skip_metadata_url_validation).to eq(false) } end describe 'validations' do @@ -65,6 +66,7 @@ end it { expect(described_class).to validate_jsonb_schema(['application_setting_rate_limits']) } + it { expect(described_class).to validate_jsonb_schema(['application_setting_package_registry']) } it { expect(described_class).to validate_jsonb_schema(['application_setting_service_ping_settings']) } diff --git a/spec/models/packages/nuget/metadatum_spec.rb b/spec/models/packages/nuget/metadatum_spec.rb index c8e052baf6f3b6..04dc2706049c53 100644 --- a/spec/models/packages/nuget/metadatum_spec.rb +++ b/spec/models/packages/nuget/metadatum_spec.rb @@ -27,6 +27,15 @@ it { is_expected.to validate_length_of(url).is_at_most(described_class::MAX_URL_LENGTH) } end + describe "skip #{url} validation" do + before do + stub_application_setting(nuget_skip_metadata_url_validation: true) + end + + it { is_expected.not_to allow_value('123').for(url) } + it { is_expected.not_to allow_value('sandbox.com').for(url) } + end + describe '#ensure_nuget_package_type' do subject { build(:nuget_metadatum) } diff --git a/spec/views/admin/application_settings/_package_registry.html.haml_spec.rb b/spec/views/admin/application_settings/_package_registry.html.haml_spec.rb index cb41f2e636ead1..9b48ba3c103315 100644 --- a/spec/views/admin/application_settings/_package_registry.html.haml_spec.rb +++ b/spec/views/admin/application_settings/_package_registry.html.haml_spec.rb @@ -66,4 +66,23 @@ expect(page).to have_content('Ultimate') end end + + context 'skip nuget package metadata url validation' do + before do + assign(:plans, [default_plan_limits.plan]) + end + + it 'renders nothing when saas', :saas do + subject + + expect(rendered).not_to have_field(s_('PackageRegistry|Skip NuGet package metadata url validations'), type: 'checkbox') + end + + it 'renders the setting checkbox when self-managed' do + subject + + expect(rendered).to have_field(s_('PackageRegistry|Skip NuGet package metadata url validations'), type: 'checkbox') + expect(page.find_field(s_('PackageRegistry|Skip NuGet package metadata url validations'))).not_to be_checked + end + end end -- GitLab From 88281b90ff0d9a14c7337cd45a902945306e52b9 Mon Sep 17 00:00:00 2001 From: MAO Chao Date: Sat, 20 Apr 2024 00:20:00 +0000 Subject: [PATCH 2/6] Apply suggestion --- app/models/packages/nuget/metadatum.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/packages/nuget/metadatum.rb b/app/models/packages/nuget/metadatum.rb index 100f9f2d83f3be..1b71ca58ccebdf 100644 --- a/app/models/packages/nuget/metadatum.rb +++ b/app/models/packages/nuget/metadatum.rb @@ -49,7 +49,7 @@ def ensure_valid_urls next if value.blank? - unless Gitlab::UrlSanitizer.valid?(value, allowed_schemes: %w[http https]) + unless Gitlab::UrlSanitizer.valid_web?(value) errors.add(field, _('is an invalid URL')) end end -- GitLab From 85219965be2585bbe5ec2f03f8c9b608f3481e9d Mon Sep 17 00:00:00 2001 From: mao chao Date: Mon, 22 Apr 2024 10:00:15 +0800 Subject: [PATCH 3/6] Fix rubocop --- app/models/packages/nuget/metadatum.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/models/packages/nuget/metadatum.rb b/app/models/packages/nuget/metadatum.rb index 1b71ca58ccebdf..71c173354a9f9e 100644 --- a/app/models/packages/nuget/metadatum.rb +++ b/app/models/packages/nuget/metadatum.rb @@ -49,9 +49,7 @@ def ensure_valid_urls next if value.blank? - unless Gitlab::UrlSanitizer.valid_web?(value) - errors.add(field, _('is an invalid URL')) - end + errors.add(field, _('is an invalid URL')) unless Gitlab::UrlSanitizer.valid_web?(value) end end end -- GitLab From e12e974e4fe865d36a387f66e251ee18727c8471 Mon Sep 17 00:00:00 2001 From: MAO Chao Date: Wed, 24 Apr 2024 07:56:55 +0000 Subject: [PATCH 4/6] Update milestone in migration --- ...0240318014850_add_package_registry_in_application_setting.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/migrate/20240318014850_add_package_registry_in_application_setting.rb b/db/migrate/20240318014850_add_package_registry_in_application_setting.rb index cad4d4a22556ff..c2900e88f8eec3 100644 --- a/db/migrate/20240318014850_add_package_registry_in_application_setting.rb +++ b/db/migrate/20240318014850_add_package_registry_in_application_setting.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class AddPackageRegistryInApplicationSetting < Gitlab::Database::Migration[2.2] - milestone '16.11' + milestone '17.0' disable_ddl_transaction! CONSTRAINT_NAME = 'check_application_settings_package_registry_is_hash' -- GitLab From 2457bfa4ae9e9d73b020be104fefaf5a79fcd12f Mon Sep 17 00:00:00 2001 From: mao chao Date: Tue, 30 Apr 2024 14:23:21 +0800 Subject: [PATCH 5/6] Update wording --- .../application_setting_package_registry.json | 2 +- .../_nuget_skip_metadata_url_validation.haml | 8 ++++---- doc/api/settings.md | 2 +- doc/development/packages/settings.md | 2 +- .../application_settings/_ee_package_registry.haml | 8 ++++---- locale/gitlab.pot | 10 +++++----- spec/features/admin/admin_settings_spec.rb | 2 +- .../_package_registry.html.haml_spec.rb | 6 +++--- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/app/validators/json_schemas/application_setting_package_registry.json b/app/validators/json_schemas/application_setting_package_registry.json index 4316041a1e45c4..bf2e67c6f42150 100644 --- a/app/validators/json_schemas/application_setting_package_registry.json +++ b/app/validators/json_schemas/application_setting_package_registry.json @@ -5,7 +5,7 @@ "properties": { "nuget_skip_metadata_url_validation": { "type": "boolean", - "description": "Indicates whether skips validation of NuGet package metadata URLs" + "description": "Indicates whether to skip metadata URL validation for the NuGet package" } }, "additionalProperties": false diff --git a/app/views/admin/application_settings/_nuget_skip_metadata_url_validation.haml b/app/views/admin/application_settings/_nuget_skip_metadata_url_validation.haml index 466b0215b8f06e..da8e4ffc57216e 100644 --- a/app/views/admin/application_settings/_nuget_skip_metadata_url_validation.haml +++ b/app/views/admin/application_settings/_nuget_skip_metadata_url_validation.haml @@ -1,15 +1,15 @@ %h5 - = s_('PackageRegistry|Skip NuGet package metadata url validations') + = s_('PackageRegistry|Skip metadata URL validation for the NuGet package') %p - = s_('PackageRegistry|By default GitLab NuGet package service will validate the %{code_open}projectUrl%{code_close}, %{code_open}iconUrl%{code_close} and %{code_open}licenseUrl%{code_close} in the package metadata. In the environment with restricted network access or air-gapped it will block the Nuget package upload as those could not be resolved. Check the option below to skip the validation.').html_safe % { code_open: ''.html_safe, code_close: ''.html_safe } + = s_('PackageRegistry|By default, the NuGet package validates the %{code_open}projectUrl%{code_close}, %{code_open}iconUrl%{code_close}, and %{code_open}licenseUrl%{code_close} metadata. In an offline environment, you cannot upload the NuGet package with this validation because these URLs cannot be resolved. You might want to select the checkbox to skip validation.').html_safe % { code_open: ''.html_safe, code_close: ''.html_safe } %p - = s_('PackageRegistry|Please consider manually validating these URLs to prevent malicious packages from being uploaded to GitLab Nuget package registry. Enabling and disabling this option can lead to invalid records in the Package Registry that cannot be updated.') + = s_('PackageRegistry|Validate these URLs manually to ensure malicious packages are not uploaded to the NuGet package registry. Selecting and clearing the checkbox might lead to invalid records in the package registry that you cannot update.') = gitlab_ui_form_for @application_setting, url: ci_cd_admin_application_settings_path(anchor: 'js-package-settings'), html: { class: 'fieldset-form' }, data: { testid: 'skip-nuget-package-metadata-url-validation-form' } do |f| = form_errors(@application_setting) %fieldset .form-group = f.gitlab_ui_checkbox_component :nuget_skip_metadata_url_validation, - s_('PackageRegistry|Skip NuGet package metadata url validations') + s_('PackageRegistry|Skip metadata URL validation for the NuGet package') = f.submit _('Save changes'), pajamas_button: true diff --git a/doc/api/settings.md b/doc/api/settings.md index 76dda0d756b31f..b1f76dfe483329 100644 --- a/doc/api/settings.md +++ b/doc/api/settings.md @@ -664,7 +664,7 @@ listed in the descriptions of the relevant settings. | `asciidoc_max_includes` | integer | no | Maximum limit of AsciiDoc include directives being processed in any one document. Default: 32. Maximum: 64. | | `duo_features_enabled` | boolean | no | Indicates whether GitLab Duo features are enabled for this instance. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144931) in GitLab 16.10. Self-managed, Premium and Ultimate only. | | `lock_duo_features_enabled` | boolean | no | Indicates whether the GitLab Duo features enabled setting is enforced for all subgroups. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144931) in GitLab 16.10. Self-managed, Premium and Ultimate only. | -| `nuget_skip_metadata_url_validation` | boolean | no | Indicates whether skips validation of NuGet package metadata URLs. | +| `nuget_skip_metadata_url_validation` | boolean | no | Indicates whether to skip metadata URL validation for the NuGet package. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/145887) in GitLab 17.0. | ### Configure inactive project deletion diff --git a/doc/development/packages/settings.md b/doc/development/packages/settings.md index 47cb0cc0a127ed..95d2e573abc559 100644 --- a/doc/development/packages/settings.md +++ b/doc/development/packages/settings.md @@ -14,7 +14,7 @@ This page includes an exhaustive list of settings related to and maintained by t | Setting | Table | Description | | ------- | ----- | -----------| -| `nuget_skip_metadata_url_validation` | `application_settings` | Enables or disables skips validation of NuGet package metadata URLs. | +| `nuget_skip_metadata_url_validation` | `application_settings` | Indicates whether to skip metadata URL validation for the NuGet package. | | `npm_package_requests_forwarding` | `application_settings` | Enables or disables npm package forwarding at the instance level. | | `pypi_package_requests_forwarding` | `application_settings` | Enables or disables PyPI package forwarding at the instance level. | | `packages_cleanup_package_file_worker_capacity` | `application_settings` | Number of concurrent workers allowed for package file cleanup. | diff --git a/ee/app/views/admin/application_settings/_ee_package_registry.haml b/ee/app/views/admin/application_settings/_ee_package_registry.haml index 763cc1022f67e3..5cff7a83177afb 100644 --- a/ee/app/views/admin/application_settings/_ee_package_registry.haml +++ b/ee/app/views/admin/application_settings/_ee_package_registry.haml @@ -30,15 +30,15 @@ - unless Gitlab.com? %h5 - = s_('PackageRegistry|Skip NuGet package metadata url validations') + = s_('PackageRegistry|Skip metadata URL validation for the NuGet package') %p - = s_('PackageRegistry|By default GitLab NuGet package service will validate the %{code_open}projectUrl%{code_close}, %{code_open}iconUrl%{code_close} and %{code_open}licenseUrl%{code_close} in the package metadata. In the environment with restricted network access or air-gapped it will block the Nuget package upload as those could not be resolved. Check the option below to skip the validation.').html_safe % { code_open: ''.html_safe, code_close: ''.html_safe } + = s_('PackageRegistry|By default, the NuGet package validates the %{code_open}projectUrl%{code_close}, %{code_open}iconUrl%{code_close}, and %{code_open}licenseUrl%{code_close} metadata. In an offline environment, you cannot upload the NuGet package with this validation because these URLs cannot be resolved. You might want to select the checkbox to skip validation.').html_safe % { code_open: ''.html_safe, code_close: ''.html_safe } %p - = s_('PackageRegistry|Please consider manually validating these URLs to prevent malicious packages from being uploaded to GitLab Nuget package registry. Enabling and disabling this option can lead to invalid records in the Package Registry that cannot be updated.') + = s_('PackageRegistry|Validate these URLs manually to ensure malicious packages are not uploaded to the NuGet package registry. Selecting and clearing the checkbox might lead to invalid records in the package registry that you cannot update.') %fieldset .form-group = f.gitlab_ui_checkbox_component :nuget_skip_metadata_url_validation, - s_('PackageRegistry|Skip NuGet package metadata url validations') + s_('PackageRegistry|Skip metadata URL validation for the NuGet package') = f.submit _('Save changes'), pajamas_button: true diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 22524fdcfa8b02..32cad95daa96bd 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -36347,7 +36347,7 @@ msgstr "" msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}" msgstr "" -msgid "PackageRegistry|By default GitLab NuGet package service will validate the %{code_open}projectUrl%{code_close}, %{code_open}iconUrl%{code_close} and %{code_open}licenseUrl%{code_close} in the package metadata. In the environment with restricted network access or air-gapped it will block the Nuget package upload as those could not be resolved. Check the option below to skip the validation." +msgid "PackageRegistry|By default, the NuGet package validates the %{code_open}projectUrl%{code_close}, %{code_open}iconUrl%{code_close}, and %{code_open}licenseUrl%{code_close} metadata. In an offline environment, you cannot upload the NuGet package with this validation because these URLs cannot be resolved. You might want to select the checkbox to skip validation." msgstr "" msgid "PackageRegistry|Composer" @@ -36667,9 +36667,6 @@ msgstr "" msgid "PackageRegistry|Pip Command" msgstr "" -msgid "PackageRegistry|Please consider manually validating these URLs to prevent malicious packages from being uploaded to GitLab Nuget package registry. Enabling and disabling this option can lead to invalid records in the Package Registry that cannot be updated." -msgstr "" - msgid "PackageRegistry|Processing" msgstr "" @@ -36742,7 +36739,7 @@ msgstr "" msgid "PackageRegistry|Show Yarn commands" msgstr "" -msgid "PackageRegistry|Skip NuGet package metadata url validations" +msgid "PackageRegistry|Skip metadata URL validation for the NuGet package" msgstr "" msgid "PackageRegistry|Some of the selected package formats allow request forwarding. Deleting a package while request forwarding is enabled for the project can pose a security risk. Do you want to proceed with deleting the selected packages? %{docLinkStart}What are the risks?%{docLinkEnd}" @@ -36826,6 +36823,9 @@ msgstr "" msgid "PackageRegistry|Users with at least the Developer role for this project will be able to publish, edit, and delete packages." msgstr "" +msgid "PackageRegistry|Validate these URLs manually to ensure malicious packages are not uploaded to the NuGet package registry. Selecting and clearing the checkbox might lead to invalid records in the package registry that you cannot update." +msgstr "" + msgid "PackageRegistry|When a package is protected then only certain user roles are able to update and delete the protected package. This helps to avoid tampering with the package." msgstr "" diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index aa763d0c90e175..ad08dcb6386673 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -504,7 +504,7 @@ visit ci_cd_admin_application_settings_path within_testid('forward-package-requests-form') do - check 'Skip NuGet package metadata url validations' + check 'Skip metadata URL validation for the NuGet package' click_button 'Save changes' end diff --git a/spec/views/admin/application_settings/_package_registry.html.haml_spec.rb b/spec/views/admin/application_settings/_package_registry.html.haml_spec.rb index 9b48ba3c103315..5af4330d7b0d03 100644 --- a/spec/views/admin/application_settings/_package_registry.html.haml_spec.rb +++ b/spec/views/admin/application_settings/_package_registry.html.haml_spec.rb @@ -75,14 +75,14 @@ it 'renders nothing when saas', :saas do subject - expect(rendered).not_to have_field(s_('PackageRegistry|Skip NuGet package metadata url validations'), type: 'checkbox') + expect(rendered).not_to have_field(s_('PackageRegistry|Skip metadata URL validation for the NuGet package'), type: 'checkbox') end it 'renders the setting checkbox when self-managed' do subject - expect(rendered).to have_field(s_('PackageRegistry|Skip NuGet package metadata url validations'), type: 'checkbox') - expect(page.find_field(s_('PackageRegistry|Skip NuGet package metadata url validations'))).not_to be_checked + expect(rendered).to have_field(s_('PackageRegistry|Skip metadata URL validation for the NuGet package'), type: 'checkbox') + expect(page.find_field(s_('PackageRegistry|Skip metadata URL validation for the NuGet package'))).not_to be_checked end end end -- GitLab From b8e48ec3e55d2a505a3417f452bcb0f83a6375a8 Mon Sep 17 00:00:00 2001 From: mao chao Date: Tue, 30 Apr 2024 17:00:12 +0800 Subject: [PATCH 6/6] Fix test in FOSS --- .../_nuget_skip_metadata_url_validation.haml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/views/admin/application_settings/_nuget_skip_metadata_url_validation.haml b/app/views/admin/application_settings/_nuget_skip_metadata_url_validation.haml index da8e4ffc57216e..0daa61b18ea4a8 100644 --- a/app/views/admin/application_settings/_nuget_skip_metadata_url_validation.haml +++ b/app/views/admin/application_settings/_nuget_skip_metadata_url_validation.haml @@ -1,10 +1,12 @@ +- return if Gitlab.com? + %h5 = s_('PackageRegistry|Skip metadata URL validation for the NuGet package') %p = s_('PackageRegistry|By default, the NuGet package validates the %{code_open}projectUrl%{code_close}, %{code_open}iconUrl%{code_close}, and %{code_open}licenseUrl%{code_close} metadata. In an offline environment, you cannot upload the NuGet package with this validation because these URLs cannot be resolved. You might want to select the checkbox to skip validation.').html_safe % { code_open: ''.html_safe, code_close: ''.html_safe } %p = s_('PackageRegistry|Validate these URLs manually to ensure malicious packages are not uploaded to the NuGet package registry. Selecting and clearing the checkbox might lead to invalid records in the package registry that you cannot update.') -= gitlab_ui_form_for @application_setting, url: ci_cd_admin_application_settings_path(anchor: 'js-package-settings'), html: { class: 'fieldset-form' }, data: { testid: 'skip-nuget-package-metadata-url-validation-form' } do |f| += gitlab_ui_form_for @application_setting, url: ci_cd_admin_application_settings_path(anchor: 'js-package-settings'), html: { class: 'fieldset-form' }, data: { testid: 'forward-package-requests-form' } do |f| = form_errors(@application_setting) %fieldset -- GitLab