# How Jenkins Implements Parameter Injection and Environment Variable Propagation

> Discover how Jenkins implements parameter injection and environment variable propagation. Learn how Jenkins treats build parameters as first-class objects to populate the environment map.

- Repository: [Jenkins/jenkins](https://github.com/jenkinsci/jenkins)
- Tags: internals
- Published: 2026-06-19

---

**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`](https://github.com/jenkinsci/jenkins/blob/main/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`](https://github.com/jenkinsci/jenkins/blob/main/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:

1. **User Submission** – When a job triggers via UI, API, or upstream job, the request parses through a concrete `ParameterDefinition` which instantiates a `ParameterValue` and stores it in a new `ParametersAction`.

2. **Queue Attachment** – The `ParametersAction` attaches to the `Queue.Item` as a `QueueAction`, ensuring parameters persist while the build waits for an executor.

3. **Run Attachment** – When the queue item converts to a `Run`, the same `ParametersAction` attaches to the run object via `RunAction2`.

4. **Environment Preparation** – Before any build steps execute, Jenkins calls `ParametersAction.buildEnvironment(Run, EnvVars)`. This method iterates through the parameter list and invokes each `ParameterValue.buildEnvironment(Run, EnvVars)`.

5. **Variable Exposure** – Concrete implementations populate the `EnvVars` map (defined in [`core/src/main/java/hudson/util/EnvVars.java`](https://github.com/jenkinsci/jenkins/blob/main/core/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`](https://github.com/jenkinsci/jenkins/blob/main/core/src/main/java/hudson/model/ParametersDefinitionProperty.java).

## Practical Implementation Examples

The following pipeline demonstrates automatic parameter injection:

```groovy
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`:

```java
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.java`](https://github.com/jenkinsci/jenkins/blob/main/core/src/main/java/hudson/model/ParametersAction.java) coordinates parameter transport by implementing `EnvironmentContributingAction` and attaching to both queue items and runs.
- **ParameterValue** subclasses in [`core/src/main/java/hudson/model/ParameterValue.java`](https://github.com/jenkinsci/jenkins/blob/main/core/src/main/java/hudson/model/ParameterValue.java) define specific environment variable mappings through the `buildEnvironment()` method.
- The injection flow moves from user submission → queue attachment → run attachment → environment preparation, ensuring deterministic propagation.
- Security filtering via `filter()` and system properties `keepUndefinedParameters` and `safeParameters` prevents unauthorized parameter injection.
- The `EnvVars` class 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.