Secrets and Key Vault: Retrieve Carefully, Never Echo
Separate keys, secrets and certificates, integrate protected stores into pipelines, and prevent leakage through logs and artifacts.
A safe needs both a lock and careful handling
Putting a password in Key Vault protects its storage and access path. Printing it in the next pipeline step defeats that protection. Secret management spans creation, authorization, retrieval, use, rotation, revocation, and deletion.
| Object | Purpose | Important distinction |
|---|---|---|
| Secret | Store a sensitive value | The consuming process can receive the value |
| Key | Perform supported cryptographic operations | Key operations need not expose private key material |
| Certificate | Manage a certificate and related lifecycle | Exportability and private-key handling matter |
| Secure file | Distribute a protected file to authorized tasks | Downloaded content still needs safe handling |
Do not call every object βa secretβ when designing permissions. Reading a certificateβs public metadata is different from retrieving an exportable private key.
Azure Pipelines: choose the integration
A variable group can link selected Azure Key Vault secrets. The group maps secret names and retrieves values through the configured service connection when used. It is not a generic synchronization mechanism for Key Vault keys and certificates.
Check vault access, network path, service-connection authentication, variable-group authorization, and the consuming task. Adding a new secret to a vault does not mean every existing variable-group mapping automatically includes its name.
A task-based alternative can fetch selected secrets through an authorized connection:
steps:
- task: AzureKeyVault@2
inputs:
azureSubscription: learning-sandbox-connection
KeyVaultName: YOUR-SANDBOX-VAULT
SecretsFilter: LearningSecret
RunAsPreJob: false
This fragment is illustrative. It requires an existing approved connection, accessible vault, and appropriate secret-read permissions. Use a harmless test value in your own sandbox. Do not add a following echo $(LearningSecret) step.
Map the secret into only the process that needs it, preferably through the taskβs supported environment/input mechanism. Avoid command-line arguments that are exposed through process listings or logs.
GitHub Actions: authenticate, retrieve, consume
Use OIDC to authenticate to Azure where supported, then retrieve the required Key Vault value with the authorized identity and a current approved action or CLI pattern. Keep retrieved values out of outputs/artifacts; register a dynamically retrieved sensitive value with the platformβs masking mechanism before any possible logging.
Masking is a last line of defense, not a guarantee. A transformed value, substring, structured JSON field, exception, or external tool can escape expected redaction. Avoid tracing commands and dumping environments.
GitHub repository, organization, and environment secrets have different availability and policy boundaries. Environment protection can gate their use. Untrusted PR events have additional restrictions. Do not switch to a privileged event merely to expose a secret to untrusted code.
Copilot cloud agent has its own documented Agents secret/variable context. Do not assume Actions secrets automatically appear in every AI execution surface.
Use secure files narrowly
Azure Pipelines secure files can hold sensitive deployment material such as signing files. Apply library security, pipeline authorization, and approvals/checks as appropriate. A download task makes the file available on an agent; it does not make every later script trustworthy.
Prefer short-lived/secretless mechanisms where feasible. When a file is necessary, limit the task scope, avoid copying it into the repository or published output, and verify cleanup according to the task/platform behavior. Protect persistent runners against residual data.
Prevent leaks before they happen
| Leak path | Preventive action |
|---|---|
| Source commit | Secret scanning/push protection and approved configuration patterns |
| Shell trace or debug dump | Disable sensitive tracing; log identifiers, not values |
| Build output | Inspect generated configuration and artifacts |
| Test failure | Redact connection strings and request headers |
| Assistant context | Share only necessary redacted diagnostics |
| Persistent runner | Isolate jobs and manage residual files/credentials |
Rotate on schedule and after suspected exposure. Version changes in Key Vault do not automatically update every consumerβs cache or restart behavior. Verify the actual application can use the new credential before revoking the old one under a planned rotation procedure, unless incident severity requires immediate revocation.
A pipeline retrieves a secret from Key Vault and then writes it into a diagnostic artifact. Is the value protected?
Try it: inspect a secretβs full path
Prerequisites: a sandbox pipeline/vault you may inspect, or a paper exercise. Do not use a real credential as test data. Vault operations and CI can incur charges.
Draw storage -> identity -> task -> process -> logs/output -> cleanup. At each arrow, identify who can read the value. Inspect a harmless test integration without echoing its value. Verify success through a non-sensitive result, not a plaintext print.
Expected observation: the pipeline can establish that a step completed without exposing the secret itself. You can identify where masking alone would be insufficient.
Cleanup: remove only your exercise secret/version and test files according to sandbox policy. Do not purge shared vault data or disable production credentials.
Decision check: rotate or just delete the log?
If a usable credential was exposed, revoke/rotate according to incident policy and investigate access. Removing one visible log does not invalidate copies or the credential itself.