VYPR
Moderate severityNVD Advisory· Published Dec 26, 2022· Updated Apr 14, 2025

CVE-2019-14802

CVE-2019-14802

Description

HashiCorp Nomad 0.5.0 through 0.9.4 (fixed in 0.9.5) reveals unintended environment variables to the rendering task during template rendering, aka GHSA-6hv3-7c34-4hx8. This applies to nomad/client/allocrunner/taskrunner/template.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

HashiCorp Nomad 0.5.0–0.9.4 leaks host environment variables to task template rendering, allowing potential information disclosure; fixed in 0.9.5.

Vulnerability

Description

CVE-2019-14802 is an information disclosure vulnerability in HashiCorp Nomad versions 0.5.0 through 0.9.4. During template rendering, the task runner passed the full host process environment to consul-template, which falls back to the host environment if a variable is not explicitly set in the task configuration. This allowed task templates to access environment variables from the host system, not just those intended for the task [1][2].

Exploitation

An attacker with the ability to submit or modify a job (and thus control the task's template) could craft templates to read host environment variables. No additional authentication beyond job submission privileges is required. The vulnerability is triggered during the normal template rendering process, making it accessible to any user who can define a task template [1][4].

Impact

Successful exploitation leads to the unintended disclosure of environment variables from the host system. These variables may contain sensitive information such as API keys, tokens, or other secrets, potentially enabling further privilege escalation or lateral movement within the infrastructure [1][4].

Mitigation

The vulnerability is fixed in Nomad 0.9.5. The fix introduces a maskProcessEnv function that masks out any environment variable not present in the task's own environment, ensuring only task-specific variables are available to consul-template [2][4]. Users are strongly advised to upgrade to 0.9.5 or later. No workaround is documented.

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/hashicorp/nomadGo
< 0.9.50.9.5

Affected products

2

Patches

1
e8238305ef0b

Render consul templates using task env only (#6055)

https://github.com/hashicorp/nomadMahmood AliAug 5, 2019via ghsa
2 files changed · +67 2
  • client/allocrunner/taskrunner/template/template.go+20 2 modified
    @@ -508,8 +508,12 @@ func templateRunner(config *TaskTemplateManagerConfig) (
     		return nil, nil, err
     	}
     
    -	// Set Nomad's environment variables
    -	runner.Env = config.EnvBuilder.Build().All()
    +	// Set Nomad's environment variables.
    +	// consul-template falls back to the host process environment if a
    +	// variable isn't explicitly set in the configuration, so we need
    +	// to mask the environment out to ensure only the task env vars are
    +	// available.
    +	runner.Env = maskProcessEnv(config.EnvBuilder.Build().All())
     
     	// Build the lookup
     	idMap := runner.TemplateConfigMapping()
    @@ -525,6 +529,20 @@ func templateRunner(config *TaskTemplateManagerConfig) (
     	return runner, lookup, nil
     }
     
    +// maskProcessEnv masks away any environment variable not found in task env.
    +// It manipulates the parameter directly and returns it without copying.
    +func maskProcessEnv(env map[string]string) map[string]string {
    +	procEnvs := os.Environ()
    +	for _, e := range procEnvs {
    +		ekv := strings.SplitN(e, "=", 2)
    +		if _, ok := env[ekv[0]]; !ok {
    +			env[ekv[0]] = ""
    +		}
    +	}
    +
    +	return env
    +}
    +
     // parseTemplateConfigs converts the tasks templates in the config into
     // consul-templates
     func parseTemplateConfigs(config *TaskTemplateManagerConfig) (map[ctconf.TemplateConfig]*structs.Template, error) {
    
  • client/allocrunner/taskrunner/template/template_test.go+47 0 modified
    @@ -16,6 +16,7 @@ import (
     	"github.com/hashicorp/nomad/client/config"
     	"github.com/hashicorp/nomad/client/taskenv"
     	"github.com/hashicorp/nomad/helper"
    +	"github.com/hashicorp/nomad/helper/uuid"
     	"github.com/hashicorp/nomad/nomad/mock"
     	"github.com/hashicorp/nomad/nomad/structs"
     	sconfig "github.com/hashicorp/nomad/nomad/structs/config"
    @@ -1022,6 +1023,52 @@ func TestTaskTemplateManager_Signal_Error(t *testing.T) {
     	require.Contains(harness.mockHooks.KillEvent.DisplayMessage, "failed to send signals")
     }
     
    +// TestTaskTemplateManager_FiltersProcessEnvVars asserts that we only render
    +// environment variables found in task env-vars and not read the nomad host
    +// process environment variables.  nomad host process environment variables
    +// are to be treated the same as not found environment variables.
    +func TestTaskTemplateManager_FiltersEnvVars(t *testing.T) {
    +	t.Parallel()
    +
    +	defer os.Setenv("NOMAD_TASK_NAME", os.Getenv("NOMAD_TASK_NAME"))
    +	os.Setenv("NOMAD_TASK_NAME", "should be overridden by task")
    +
    +	testenv := "TESTENV_" + strings.ReplaceAll(uuid.Generate(), "-", "")
    +	os.Setenv(testenv, "MY_TEST_VALUE")
    +	defer os.Unsetenv(testenv)
    +
    +	// Make a template that will render immediately
    +	content := `Hello Nomad Task: {{env "NOMAD_TASK_NAME"}}
    +TEST_ENV: {{ env "` + testenv + `" }}
    +TEST_ENV_NOT_FOUND: {{env "` + testenv + `_NOTFOUND" }}`
    +	expected := fmt.Sprintf("Hello Nomad Task: %s\nTEST_ENV: \nTEST_ENV_NOT_FOUND: ", TestTaskName)
    +
    +	file := "my.tmpl"
    +	template := &structs.Template{
    +		EmbeddedTmpl: content,
    +		DestPath:     file,
    +		ChangeMode:   structs.TemplateChangeModeNoop,
    +	}
    +
    +	harness := newTestHarness(t, []*structs.Template{template}, false, false)
    +	harness.start(t)
    +	defer harness.stop()
    +
    +	// Wait for the unblock
    +	select {
    +	case <-harness.mockHooks.UnblockCh:
    +	case <-time.After(time.Duration(5*testutil.TestMultiplier()) * time.Second):
    +		require.Fail(t, "Task unblock should have been called")
    +	}
    +
    +	// Check the file is there
    +	path := filepath.Join(harness.taskDir, file)
    +	raw, err := ioutil.ReadFile(path)
    +	require.NoError(t, err)
    +
    +	require.Equal(t, expected, string(raw))
    +}
    +
     // TestTaskTemplateManager_Env asserts templates with the env flag set are read
     // into the task's environment.
     func TestTaskTemplateManager_Env(t *testing.T) {
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

8

News mentions

0

No linked articles in our index yet.