azure-devops-variable-group-can-read-secret
A pipeline that references a non-Key Vault variable group has the group's secret variables injected into every job's environment; pipeline code can read and log them.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
node_type(?pipeline) ==
BuildWorker
node_type(?variable_group) == Secret
?variable_group.provider_type == Microsoft.DevOps/variablegroups
NOT (?variable_group.linkType == AzureKeyVault)
?variable_group is referenced in ?pipeline's YAML variables: block or classic-pipeline variable group
emit
| source type | BuildWorker |
|---|---|
| target type | Secret |
| source | ?pipeline |
| target | ?variable_group |
| permissions | Use permission on variable group (DevOps Library namespace) |
| state logic | ACTIVE when the variable group is accessible to the pipeline (pipeline granted 'Use' permission on the VG in DevOps Library) and the variable group contains at least one secret variable. Exclude Key Vault-linked VGs; those are handled by azure-devops-kv-variable-group-can-read-secret. |
Narrative
{pipeline.name} references variable group {variable_group.name}; all secret variables in the group are injected as environment variables into pipeline job steps and are fully readable by pipeline code (DevOps log masking is not a security boundary).
Raw rule rules/derived/azure/devops.yaml
id: azure-devops-variable-group-can-read-secret
emits: CanReadSecret
description: A pipeline that references a non-Key Vault variable group has the group's secret variables
injected into every job's environment; pipeline code can read and log them.
applies_to:
- azure
match:
- - pipeline: null
- HasPolicy
- variable_group: null
where:
- node_type(?pipeline) == BuildWorker
- node_type(?variable_group) == Secret
- ?variable_group.provider_type == Microsoft.DevOps/variablegroups
- NOT (?variable_group.linkType == AzureKeyVault)
- '?variable_group is referenced in ?pipeline''s YAML variables: block or classic-pipeline variable group'
emit:
source_type: BuildWorker
target_type: Secret
source: ?pipeline
target: ?variable_group
permissions:
- Use permission on variable group (DevOps Library namespace)
conditions: []
state_logic: ACTIVE when the variable group is accessible to the pipeline (pipeline granted 'Use' permission
on the VG in DevOps Library) and the variable group contains at least one secret variable. Exclude
Key Vault-linked VGs; those are handled by azure-devops-kv-variable-group-can-read-secret.
confidence: 0.9
derived_from: []
false_positive_note: "DevOps secret variable masking does NOT constitute a security boundary \u2014\
\ the mask only prevents the value from appearing in UI logs. Code can still print the value to a\
\ file, send it over the network, or read it via $env:VAR_NAME. Do NOT treat masking as access control.\
\ This rule applies only to non-Key Vault VGs; Key Vault- linked VGs have resource_policy gates (RBAC\
\ on the Key Vault) \u2014 do not emit ACTIVE for them here."
narrative: '{pipeline.name} references variable group {variable_group.name}; all secret variables in
the group are injected as environment variables into pipeline job steps and are fully readable by
pipeline code (DevOps log masking is not a security boundary).'