GitLab CI/CD variables:expand:false Raw & Nested Variable Prompt
Stop GitLab from mangling secrets and tokens that contain dollar signs or look like variable references by using variables:expand:false (raw variables), and design intentional nested expansion where you actually want it.
- Target user
- Engineers debugging garbled tokens, passwords, and connection strings in CI
- Difficulty
- Intermediate
- Tools
- Claude, ChatGPT
The prompt
You are a GitLab CI variables expert who knows exactly when and how GitLab expands `$VAR` references inside variable values — and how to turn that off when it corrupts a value.
I will provide:
- The variable(s) and where they're defined (project/group CI settings, .gitlab-ci.yml, or passed downstream)
- The value's shape (token with literal `$`, password, connection string, regex, JSON)
- The symptom (value arrives truncated, blanked, or with `$something` replaced by empty/wrong text)
Your job:
1. **Explain the expansion model** — GitLab runs variable expansion on variable *values* by default, so any `$NAME` or `${NAME}` inside a value is substituted, and a literal `$` followed by characters can be eaten. State which definition layers expand and the order they resolve.
2. **Diagnose my symptom** — given my value's shape, identify whether unwanted expansion is corrupting it (e.g., a token containing `$abc` gets `$abc` resolved to empty).
3. **Fix with raw variables** — show the `variables:` long form using `value:` and `expand: false` so the value is treated literally. Provide the exact YAML for my case.
4. **Intentional nesting** — for the cases where I DO want composition (e.g., building a URL from `$HOST` and `$PORT`), show the correct nested-expansion pattern and note that `expand: false` on the outer var blocks nesting.
5. **Masking interaction** — warn how raw values, special characters, and length affect variable masking, and what makes a value unmaskable.
6. **Verify** — give a one-line debug job that echoes the value safely (without leaking a real secret) to confirm it arrives intact, plus how to check via the job's expanded-variables.
Output: (a) the diagnosis, (b) the corrected `variables:` block with `expand: false` where needed, (c) the intentional-nesting example, (d) masking caveats, (e) the verify job.
Bias toward: treating secrets and tokens as raw by default, and only enabling expansion where composition is intended.
Run this prompt with AI
Test it, get an AI-improved version, or compare models — live in the Prompt Workspace. No copy-paste.
Why this prompt works
GitLab expands variable references inside variable values by default, and almost nobody knows this until it bites. A perfectly valid access token that happens to contain $ followed by letters arrives in the job mangled, because GitLab tried to resolve $letters as another variable and substituted empty string. The same thing happens to passwords, regex patterns, and JSON blobs. The symptom is maddening — the value is correct in the settings UI but wrong in the job — and people waste hours suspecting masking, encoding, or the runner before they learn the real cause. This prompt front-loads the expansion model so the diagnosis comes fast.
The fix, variables:expand:false, is a single key, but it lives inside the long-form value:/expand: syntax that you only reach for when you already know it exists. By having the model produce the exact corrected block for your specific value shape, you skip the syntax archaeology. Just as important, the prompt covers the other direction: sometimes you genuinely want ${HOST}:${PORT} to compose, and turning expansion off everywhere would break that. Distinguishing the two cases is the whole skill, and the prompt makes the model do it explicitly rather than blanket-disabling expansion.
Finally, raw values interact with masking in non-obvious ways — certain characters and lengths make a value unmaskable, which can turn a “fix” into a secret-leak. Folding the masking caveat and a safe verify job into the same answer means you don’t fix the expansion bug only to create a logging problem. That end-to-end framing is what separates a usable answer from a one-liner that creates its own incident.
Related prompts
-
GitLab CI/CD Variables Debugging Prompt
Diagnose why a GitLab CI/CD variable is missing, masked oddly, expanded wrong, or scoped to the wrong environment — protected, masked, file-type, inheritance, environment scope.
-
GitLab CI/CD Variable Precedence & Scope Audit Prompt
Audit where a CI/CD variable's value actually comes from when project, group, instance, and YAML-defined variables collide and produce surprising overrides.
-
GitLab CI/CD needs: Graph Deadlock & Missing-Job Debug Prompt
Debug DAG pipelines that error with 'job X needs Y which is not present', skip jobs unexpectedly, or run in the wrong order because needs:, stages, and rules disagree about which jobs exist in the graph.
-
GitLab CI/CD Protected Variable Leak & Log Exposure Audit Prompt
Audit a .gitlab-ci.yml and project CI/CD settings for ways secrets leak into job logs, forks, or MR pipelines via unmasked variables, echoed env, expanded interpolation, or protected/masked misconfiguration.
More GitLab CI/CD prompts & error guides
Browse every GitLab CI/CD prompt and troubleshooting guide in one place.
Reading prompts? Get all 500 in one free PDF
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.