How to securely use variables and parameters in your pipeline
This article discusses how to securely use variables and parameters to gather input from pipeline users.
Variables can be a convenient way to collect information from the user up front. You can also use variables to pass data from step to step within a pipeline.
But use variables with caution. Newly created variables, whether they're defined in YAML or written by a script, are read-write by default. A downstream step can change the value of a variable in a way that you don't expect.
For instance, imagine your script reads:
msbuild.exe myproj.proj -property:Configuration=$(MyConfig)
A preceding step could set
Debug & deltree /y c:.
Although this example would only delete the contents of your build agent, you can imagine how this setting could easily become far more dangerous.
You can make variables read-only.
System variables like
Build.SourcesDirectory, task output variables, and queue-time variables are always read-only.
Variables that are created in YAML or created at run time by a script can be designated as read-only.
When a script or task creates a new variable, it can pass the
isReadonly=true flag in its logging command to make the variable read-only.
In YAML, you can specify read-only variables by using a specific key:
variables: - name: myReadOnlyVar value: myValue readonly: true
Queue-time variables are exposed to the end user who manually runs a pipeline. As originally designed, this concept was only for the UI. The underlying API would accept user overrides of any variable, even variables that weren't designated as queue-time variables. This arrangement was confusing and insecure. So we've added a setting that makes the API accept only variables that can be set at queue time. We recommend that you turn on this setting.
Unlike variables, pipeline parameters can't be changed by a pipeline while it's running.
Parameters have data types such as
string, and they can be restricted to a subset of values.
Restricting the parameters is useful when a user-configurable part of the pipeline should take a value only from a constrained list. The setup ensures that the pipeline won't take arbitrary data.
After you secure your inputs, you also need to secure your shared infrastructure.