Enable "Masked and hidden" visibility option for instance-level CI/CD variables in Admin UI
Summary
The "Masked and hidden" visibility option is available for project-level and group-level CI/CD variables in the UI, but it is not available for instance-level variables in the Admin Area UI. However, the backend (REST API) already fully supports creating instance variables with masked_and_hidden=true.
This means the feature works via API but is intentionally disabled in the frontend for instance variables, creating an inconsistency.
Steps to reproduce
- Go to Admin Area > CI/CD > Variables
- Click Add variable
- Observe that the Visibility section only offers Visible and Masked, but not "Masked and hidden"
Compare with:
- Go to any Project > Settings > CI/CD > Variables
- Click Add variable
- The Visibility section correctly offers Visible, Masked, and Masked and hidden
Root cause
In ci_variable_shared.vue (line ~165):
areHiddenVariablesAvailable() {
// group and project variables can be hidden, instance variables cannot
return Boolean(this.entity);
},
The entity prop is not set by ci_admin_variables.vue, so it defaults to an empty string '', causing Boolean('') to return false. This hides the "Masked and hidden" radio button in the variable drawer.
Backend already supports this
Creating a masked and hidden instance variable via the API works without issues:
curl --request POST \
--header "PRIVATE-TOKEN: <admin-token>" \
"https://gitlab.example.com/api/v4/admin/ci/variables" \
--form "key=MY_SECRET_KEY" \
--form "value=my-secret-value" \
--form "masked_and_hidden=true"
This confirms that the database schema, model validations, and API layer are all ready for instance-level hidden variables.
Proposed fix
Option A — Set the entity prop in ci_admin_variables.vue:
<ci-variable-shared
:are-scoped-variables-available="false"
component-name="InstanceVariables"
+ entity="instance"
:hide-environment-scope="true"
:mutation-data="$options.mutationData"
:refetch-after-mutation="true"
:query-data="$options.queryData"
/>
Option B — Decouple the logic in ci_variable_shared.vue so it no longer uses entity as a proxy:
areHiddenVariablesAvailable() {
- // group and project variables can be hidden, instance variables cannot
- return Boolean(this.entity);
+ return true;
},
Both options are minimal changes. Option A may be preferred as it also makes the entity prop consistent across all variable components.
Related closed issues
- #29674 (closed) (Frontend: Add "Masked and hidden" option — explicitly scoped out instance variables)
- #390305 (closed) (Backend: Create database column for hidden variables — completed)
Environment
Reproducible on GitLab Self-Managed (tested on 18.8) and confirmed by reading the current master branch source code.