How Jenkins Implements Parameter Injection and Environment Variable Propagation
Jenkins treats build parameters as first-class objects that travel with a build from queue to completion, using ParametersAction to attach them to both the queue item and the run, then delegates to each ParameterValue to populate the environment map.
The jenkinsci/jenkins repository implements parameter injection and environment variable propagation through a dedicated action-based system that bridges user input with runtime environment configuration. This design ensures that parameters defined at job configuration time become available as shell environment variables during build execution while maintaining strict security controls over which values propagate.
Core Architecture Components
ParametersAction: The Environment Coordinator
The ParametersAction class in core/src/main/java/hudson/model/ParametersAction.java serves as the primary vehicle for parameter transport. It implements RunAction2 and EnvironmentContributingAction, allowing it to attach to both the queue item before execution and the run object during execution.
This class holds a list of ParameterValue objects in its parameters field. When Jenkins prepares the build environment, it invokes ParametersAction.buildEnvironment(Run<?,?>, EnvVars), which iterates over all parameters and delegates to each ParameterValue to add its specific entries to the environment map.
ParameterValue: The Variable Source
Individual parameters are represented by the abstract ParameterValue class located in core/src/main/java/hudson/model/ParameterValue.java. Concrete implementations such as StringParameterValue and BooleanParameterValue override the buildEnvironment(Run<?,?>, EnvVars) method to define exactly which environment variables they expose.
The class also provides createVariableResolver(AbstractBuild) to support variable substitution in build steps, enabling token expansion like ${PARAMETER_NAME} within job configurations.
The Parameter Injection Flow
Jenkins parameter injection follows a deterministic lifecycle from user submission to environment availability:
-
User Submission – When a job triggers via UI, API, or upstream job, the request parses through a concrete
ParameterDefinitionwhich instantiates aParameterValueand stores it in a newParametersAction. -
Queue Attachment – The
ParametersActionattaches to theQueue.Itemas aQueueAction, ensuring parameters persist while the build waits for an executor. -
Run Attachment – When the queue item converts to a
Run, the sameParametersActionattaches to the run object viaRunAction2. -
Environment Preparation – Before any build steps execute, Jenkins calls
ParametersAction.buildEnvironment(Run, EnvVars). This method iterates through the parameter list and invokes eachParameterValue.buildEnvironment(Run, EnvVars). -
Variable Exposure – Concrete implementations populate the
EnvVarsmap (defined incore/src/main/java/hudson/util/EnvVars.java), making values available to shell steps, scripts, and downstream jobs.
Security Filtering and Safe Parameters
The ParametersAction.filter() method implements security-conscious parameter validation. By default, it removes parameters that are not defined in the job's ParametersDefinitionProperty unless an administrator explicitly opts in via the -DkeepUndefinedParameters=true system property or whitelists specific names using -DsafeParameters.
When undefined parameters are filtered, Jenkins logs a warning to help administrators identify accidental or malicious injection attempts. This validation occurs against the job-level definitions stored in core/src/main/java/hudson/model/ParametersDefinitionProperty.java.
Practical Implementation Examples
The following pipeline demonstrates automatic parameter injection:
pipeline {
agent any
parameters {
string(name: 'GREETING', defaultValue: 'Hello', description: 'Greeting text')
}
stages {
stage('Print') {
steps {
// Automatic injection makes GREETING available as env.GREETING
echo "${env.GREETING}, world!"
// Access via VariableResolver for programmatic use
script {
def resolver = currentBuild.rawBuild.getBuildVariableResolver()
echo "Resolved: ${resolver.resolve('GREETING')}"
}
}
}
}
}
When executed, Jenkins creates a StringParameterValue for GREETING and the ParametersAction adds GREETING=Hello to the environment through StringParameterValue.buildEnvironment.
To create custom environment variables, extend ParameterValue:
public class MyPairParameterValue extends ParameterValue {
private final String first;
private final String second;
public MyPairParameterValue(String name, String first, String second) {
super(name);
this.first = first;
this.second = second;
}
@Override
public void buildEnvironment(Run<?,?> build, EnvVars env) {
env.put(name + "_FIRST", first);
env.put(name + "_SECOND", second);
}
}
This implementation makes MYPAIR_FIRST and MYPAIR_SECOND available to subsequent build steps when stored in a ParametersAction.
Summary
- ParametersAction in
core/src/main/java/hudson/model/ParametersAction.javacoordinates parameter transport by implementingEnvironmentContributingActionand attaching to both queue items and runs. - ParameterValue subclasses in
core/src/main/java/hudson/model/ParameterValue.javadefine specific environment variable mappings through thebuildEnvironment()method. - The injection flow moves from user submission → queue attachment → run attachment → environment preparation, ensuring deterministic propagation.
- Security filtering via
filter()and system propertieskeepUndefinedParametersandsafeParametersprevents unauthorized parameter injection. - The
EnvVarsclass provides the map structure that makes variables available to all build steps and downstream jobs.
Frequently Asked Questions
How does Jenkins prevent malicious parameter injection?
Jenkins prevents unauthorized parameter injection through the ParametersAction.filter() method, which validates parameters against the job's ParametersDefinitionProperty. Undefined parameters are automatically removed unless the administrator sets -DkeepUndefinedParameters=true or whitelists specific parameter names via -DsafeParameters. This ensures only explicitly configured parameters reach the build environment.
What is the difference between ParametersAction and ParameterValue?
ParametersAction is a container that holds multiple parameters and attaches to the build lifecycle (queue and run), while ParameterValue represents a single named value. The action delegates environment variable creation to each value object, allowing specific parameter types like StringParameterValue or BooleanParameterValue to define their own variable naming conventions and formats.
Can custom plugins add environment variables through this mechanism?
Yes, custom plugins can extend ParameterValue and override buildEnvironment(Run<?,?>, EnvVars) to inject custom environment variables. The custom value must be stored in a ParametersAction attached to the build. This approach integrates automatically with Jenkins' environment setup phase without requiring additional build wrappers.
When are build parameters available during pipeline execution?
Build parameters are available immediately when the pipeline starts executing, before any stage steps run. During the environment preparation phase, Jenkins calls ParametersAction.buildEnvironment(), which populates the EnvVars map. This occurs after the run attaches to the queue item but before the first build step executes, ensuring parameters are available to all scripts, shell commands, and tool invocations.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →