Repository: hashicorp/packer (Go)

Issue:
Sensitive variables are logged when escaped for powershell
<!--- Please keep this note for the community --->

#### Community Note

* Please vote on this issue by adding a 👍 [reaction](https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) to the original issue to help the community and maintainers prioritize this request
* Please do not leave "+1" or other comments that do not add relevant new information or questions, they generate extra noise for issue followers and do not help prioritize the request
* If you are interested in working on this issue or have submitted a pull request, please leave a comment

<!--- Thank you for keeping this note for the community --->

#### Overview of the Issue

When sensitive variables contain characters that require escaping the logs will print that sensitive variable in its escaped form.

#### Reproduction Steps

Run example from powershell with PACKER_LOG=1:

```
$Env:PACKER_LOG=1;& .\packer.exe build -var password="abc`$123" password.pkr.hcl
```

### Packer version

Packer v1.10.2

### Simplified Packer Template


```
variable "password" {
  type    = string
  sensitive = true
}

source "file" "basic-example" {
  content =  "Lorem ipsum dolor sit amet"
  target =  "dummy_artifact"
}

build {
  sources = ["sources.file.basic-example"]

  provisioner "powershell" {
    environment_vars = [
      "PASSWORD=${var.password}",
    ]
    inline = ["echo foo"]
  }
}
```

### Operating system and Environment details

Windows Server 2022

### Log Fragments and crash.log files

```
2024/04/12 10:11:48 packer.exe plugin: Env var <sensitive> converted to abc`$123 after escaping chars special to PS
```

[Full Logs](https://gist.github.com/zinkj/813d23131dc112aa0c75a52c7ad4fb83)




Discussion:
Hi @zinkj,

Thanks for the report, looking at the problem however, I'm not sure we'll be able to offer a good solution with the current architecture regarding log filtering.

The way we do things re:sensitive variables is essentially by `strings.Replace(sensitiveVariable, "<sensitive>", -1)`, which in effect if the variable gets escaped one way or another, won't match anymore.
We don't have agency on what gets printed by custom code, and it wouldn't be feasible to support every possible escaping scheme under the sun, therefore I'm not sure we have a good way to handle cases like these, at least without seriously rethinking/refactoring how this gets printed out.

I'll keep this issue open for now, but this seems like unlikely to happen in the short/medium term, sorry.
I'm going to lock this issue because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.



Patch:
diff --git a/go.mod b/go.mod
index 7b231ff0850..4ec3e10a0f0 100644
--- a/go.mod
+++ b/go.mod
@@ -23,7 +23,7 @@ require (
 	github.com/hashicorp/go-version v1.6.0
 	github.com/hashicorp/hcl/v2 v2.19.1
 	github.com/hashicorp/hcp-sdk-go v0.136.0
-	github.com/hashicorp/packer-plugin-sdk v0.6.0
+	github.com/hashicorp/packer-plugin-sdk v0.6.2
 	github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869
 	github.com/klauspost/compress v1.13.6
 	github.com/klauspost/pgzip v1.2.5
@@ -44,14 +44,14 @@ require (
 	github.com/zclconf/go-cty v1.13.3
 	github.com/zclconf/go-cty-yaml v1.0.1
 	golang.org/x/crypto v0.36.0 // indirect
-	golang.org/x/mod v0.19.0
+	golang.org/x/mod v0.24.0
 	golang.org/x/net v0.38.0
 	golang.org/x/oauth2 v0.27.0
 	golang.org/x/sync v0.12.0
 	golang.org/x/sys v0.31.0 // indirect
 	golang.org/x/term v0.30.0 // indirect
 	golang.org/x/text v0.23.0
-	golang.org/x/tools v0.23.0
+	golang.org/x/tools v0.31.0
 	google.golang.org/api v0.150.0 // indirect
 	google.golang.org/grpc v1.59.0
 )
@@ -75,7 +75,7 @@ require (
 	github.com/Masterminds/goutils v1.1.1 // indirect
 	github.com/Masterminds/semver/v3 v3.1.1 // indirect
 	github.com/Masterminds/sprig/v3 v3.2.1 // indirect
-	github.com/Microsoft/go-winio v0.6.1 // indirect
+	github.com/Microsoft/go-winio v0.6.2 // indirect
 	github.com/ProtonMail/go-crypto v1.1.3 // indirect
 	github.com/agext/levenshtein v1.2.3 // indirect
 	github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect
@@ -180,7 +180,7 @@ require (
 	go.opentelemetry.io/otel/metric v1.17.0 // indirect
 	go.opentelemetry.io/otel/trace v1.17.0 // indirect
 	golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
-	golang.org/x/time v0.3.0 // indirect
+	golang.org/x/time v0.11.0 // indirect
 	golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
 	google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect
 	google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b // indirect
diff --git a/go.sum b/go.sum
index ff9337cb3ab..3e910fce997 100644
--- a/go.sum
+++ b/go.sum
@@ -28,8 +28,8 @@ github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0
 github.com/Masterminds/sprig/v3 v3.2.1 h1:n6EPaDyLSvCEa3frruQvAiHuNp2dhBlMSmkEr+HuzGc=
 github.com/Masterminds/sprig/v3 v3.2.1/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk=
 github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
-github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
-github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
+github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
+github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
 github.com/ProtonMail/go-crypto v1.1.3 h1:nRBOetoydLeUb4nHajyO2bKqMLfWQ/ZPwkXqXxPxCFk=
 github.com/ProtonMail/go-crypto v1.1.3/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
 github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
@@ -303,8 +303,8 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO
 github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
 github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR/prTM=
 github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0=
-github.com/hashicorp/packer-plugin-sdk v0.6.0 h1:v8JdmM1PkkHu3gIUs63UcsgGlD0U3m/7DWG6PxcmOPw=
-github.com/hashicorp/packer-plugin-sdk v0.6.0/go.mod h1:bDCCzvZ6lUJjrY7eI+i9lYmGs9NSymdFFQiGluF8dEg=
+github.com/hashicorp/packer-plugin-sdk v0.6.2 h1:XRIJTcHa9AN13ZvVjL+RpwxEz+yYT7qJ5PA2REViJZ0=
+github.com/hashicorp/packer-plugin-sdk v0.6.2/go.mod h1:mOuey53XeLIIpdOQnREjEBYCndipO7piU+EJAstQq1k=
 github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY=
 github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4=
 github.com/hashicorp/vault/api v1.14.0 h1:Ah3CFLixD5jmjusOgm8grfN9M0d+Y8fVR2SW0K6pJLU=
@@ -595,8 +595,8 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
 golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
 golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
-golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
+golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -680,8 +680,8 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
 golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
-golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
-golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
+golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@@ -691,8 +691,8 @@ golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtn
 golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
-golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
+golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
+golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
diff --git a/hcl2template/types.build.provisioners.go b/hcl2template/types.build.provisioners.go
index b08eca59f63..af846807c70 100644
--- a/hcl2template/types.build.provisioners.go
+++ b/hcl2template/types.build.provisioners.go
@@ -186,6 +186,16 @@ func (cfg *PackerConfig) startProvisioner(source SourceUseBlock, pb *Provisioner
 	builderVars["packer_force"] = strconv.FormatBool(cfg.force)
 	builderVars["packer_on_error"] = cfg.onError
 
+	sensitiveVars := make([]string, 0, len(cfg.InputVariables))
+
+	for key, variable := range cfg.InputVariables {
+		if variable.Sensitive {
+			sensitiveVars = append(sensitiveVars, key)
+		}
+	}
+
+	builderVars["packer_sensitive_variables"] = sensitiveVars
+
 	hclProvisioner := &HCL2Provisioner{
 		Provisioner:      provisioner,
 		provisionerBlock: pb,
diff --git a/hcl2template/types.hcl_post-processor.go b/hcl2template/types.hcl_post-processor.go
index b9d200758de..1d1da3a676f 100644
--- a/hcl2template/types.hcl_post-processor.go
+++ b/hcl2template/types.hcl_post-processor.go
@@ -21,7 +21,7 @@ type HCL2PostProcessor struct {
 	PostProcessor      packersdk.PostProcessor
 	postProcessorBlock *PostProcessorBlock
 	evalContext        *hcl.EvalContext
-	builderVariables   map[string]string
+	builderVariables   map[string]interface{}
 }
 
 func (p *HCL2PostProcessor) ConfigSpec() hcldec.ObjectSpec {
diff --git a/hcl2template/types.hcl_provisioner.go b/hcl2template/types.hcl_provisioner.go
index b607a0092a2..7fc84222e4c 100644
--- a/hcl2template/types.hcl_provisioner.go
+++ b/hcl2template/types.hcl_provisioner.go
@@ -21,7 +21,7 @@ type HCL2Provisioner struct {
 	Provisioner      packersdk.Provisioner
 	provisionerBlock *ProvisionerBlock
 	evalContext      *hcl.EvalContext
-	builderVariables map[string]string
+	builderVariables map[string]interface{}
 	override         map[string]interface{}
 }
 
diff --git a/hcl2template/types.packer_config.go b/hcl2template/types.packer_config.go
index 17039e82aa4..8f439788f0b 100644
--- a/hcl2template/types.packer_config.go
+++ b/hcl2template/types.packer_config.go
@@ -827,6 +827,14 @@ func (cfg *PackerConfig) GetBuilds(opts packer.GetBuildsOptions) ([]*packer.Core
 			pcb.PostProcessors = pps
 			pcb.Prepared = true
 
+			pcb.SensitiveVars = make([]string, 0, len(cfg.InputVariables))
+
+			for key, variable := range cfg.InputVariables {
+				if variable.Sensitive {
+					pcb.SensitiveVars = append(pcb.SensitiveVars, key)
+				}
+			}
+
 			// Prepare just sets the "prepareCalled" flag on CoreBuild, since
 			// we did all the prep here.
 			_, err := pcb.Prepare()
diff --git a/hcl2template/types.source.go b/hcl2template/types.source.go
index 46b9caac98e..320b5925f24 100644
--- a/hcl2template/types.source.go
+++ b/hcl2template/types.source.go
@@ -147,8 +147,8 @@ func (cfg *PackerConfig) startBuilder(source SourceUseBlock, ectx *hcl.EvalConte
 }
 
 // These variables will populate the PackerConfig inside of the builders.
-func (source *SourceUseBlock) builderVariables() map[string]string {
-	return map[string]string{
+func (source *SourceUseBlock) builderVariables() map[string]interface{} {
+	return map[string]interface{}{
 		"packer_build_name":   source.Name,
 		"packer_builder_type": source.Type,
 	}
diff --git a/packer/build.go b/packer/build.go
index 4a311461e96..aab50ab62f2 100644
--- a/packer/build.go
+++ b/packer/build.go
@@ -42,6 +42,7 @@ type CoreBuild struct {
 	CleanupProvisioner CoreBuildProvisioner
 	TemplatePath       string
 	Variables          map[string]string
+	SensitiveVars      []string
 
 	// Indicates whether the build is already initialized before calling Prepare(..)
 	Prepared bool
@@ -175,6 +176,7 @@ func (b *CoreBuild) Prepare() (warn []string, err error) {
 		common.OnErrorConfigKey:       b.onError,
 		common.TemplatePathKey:        b.TemplatePath,
 		common.UserVariablesConfigKey: b.Variables,
+		common.SensitiveVarsConfigKey: b.SensitiveVars,
 	}
 
 	// Prepare the builder
diff --git a/packer/core.go b/packer/core.go
index 70a8af761bc..8be8e61b2bf 100644
--- a/packer/core.go
+++ b/packer/core.go
@@ -494,6 +494,11 @@ func (c *Core) Build(n string) (*CoreBuild, error) {
 		postProcessors = append(postProcessors, current)
 	}
 
+	var sensitiveVars []string
+	for _, sensitive := range c.Template.SensitiveVariables {
+		sensitiveVars = append(sensitiveVars, sensitive.Key)
+	}
+
 	// TODO hooks one day
 
 	// Return a structure that contains the plugins, their types, variables, and
@@ -508,6 +513,7 @@ func (c *Core) Build(n string) (*CoreBuild, error) {
 		CleanupProvisioner: cleanupProvisioner,
 		TemplatePath:       c.Template.Path,
 		Variables:          c.variables,
+		SensitiveVars:      sensitiveVars,
 	}
 
 	//configBuilder.Name is left uninterpolated so we must check against
diff --git a/provisioner/powershell/provisioner.go b/provisioner/powershell/provisioner.go
index 901707c22a2..990f133088a 100644
--- a/provisioner/powershell/provisioner.go
+++ b/provisioner/powershell/provisioner.go
@@ -535,7 +535,16 @@ func (p *Provisioner) createFlattenedEnvVars(elevated bool) (flattened string) {
 		keyValue := strings.SplitN(envVar, "=", 2)
 		// Escape chars special to PS in each env var value
 		escapedEnvVarValue := psEscape.Replace(keyValue[1])
-		if escapedEnvVarValue != keyValue[1] {
+
+		isSensitive := false
+		for _, sensitiveVar := range p.config.PackerSensitiveVars {
+			if strings.EqualFold(sensitiveVar, keyValue[0]) {
+				isSensitive = true
+				break
+			}
+		}
+
+		if escapedEnvVarValue != keyValue[1] && !isSensitive {
 			log.Printf("Env var %s converted to %s after escaping chars special to PS", keyValue[1],
 				escapedEnvVarValue)
 		}


Test patch:
diff --git a/hcl2template/types.build.hcp_packer_registry_test.go b/hcl2template/types.build.hcp_packer_registry_test.go
index 5238c08c224..ada7b89b169 100644
--- a/hcl2template/types.build.hcp_packer_registry_test.go
+++ b/hcl2template/types.build.hcp_packer_registry_test.go
@@ -56,6 +56,7 @@ func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
 					PostProcessors: [][]packer.CoreBuildPostProcessor{},
 					Prepared:       true,
 					BuilderType:    "null",
+					SensitiveVars:  []string{},
 				},
 			},
 			false,
@@ -110,6 +111,7 @@ func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
 					PostProcessors: [][]packer.CoreBuildPostProcessor{},
 					Prepared:       true,
 					BuilderType:    "null",
+					SensitiveVars:  []string{},
 				},
 				&packer.CoreBuild{
 					BuildName:      "build2",
@@ -119,6 +121,7 @@ func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
 					PostProcessors: [][]packer.CoreBuildPostProcessor{},
 					Prepared:       true,
 					BuilderType:    "null",
+					SensitiveVars:  []string{},
 				},
 			},
 			false,
@@ -173,6 +176,7 @@ func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
 					PostProcessors: [][]packer.CoreBuildPostProcessor{},
 					Prepared:       true,
 					BuilderType:    "null",
+					SensitiveVars:  []string{},
 				},
 				&packer.CoreBuild{
 					BuildName:      "build2",
@@ -182,6 +186,7 @@ func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
 					PostProcessors: [][]packer.CoreBuildPostProcessor{},
 					Prepared:       true,
 					BuilderType:    "null",
+					SensitiveVars:  []string{},
 				},
 			},
 			false,
@@ -237,6 +242,7 @@ func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
 					PostProcessors: [][]packer.CoreBuildPostProcessor{},
 					Prepared:       true,
 					BuilderType:    "null",
+					SensitiveVars:  []string{},
 				},
 				&packer.CoreBuild{
 					BuildName:      "build2",
@@ -246,6 +252,7 @@ func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
 					PostProcessors: [][]packer.CoreBuildPostProcessor{},
 					Prepared:       true,
 					BuilderType:    "null",
+					SensitiveVars:  []string{},
 				},
 			},
 			false,
@@ -292,6 +299,7 @@ func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
 					PostProcessors: [][]packer.CoreBuildPostProcessor{},
 					Prepared:       true,
 					BuilderType:    "null",
+					SensitiveVars:  []string{},
 				},
 			},
 			false,
@@ -339,6 +347,7 @@ func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
 					Provisioners:   []packer.CoreBuildProvisioner{},
 					PostProcessors: [][]packer.CoreBuildPostProcessor{},
 					BuilderType:    "virtualbox-iso",
+					SensitiveVars:  []string{},
 				},
 			},
 			false,
@@ -399,6 +408,7 @@ func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
 					Provisioners:   []packer.CoreBuildProvisioner{},
 					PostProcessors: [][]packer.CoreBuildPostProcessor{},
 					BuilderType:    "virtualbox-iso",
+					SensitiveVars:  []string{},
 				},
 			},
 			false,
@@ -605,6 +615,7 @@ func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
 					PostProcessors: [][]packer.CoreBuildPostProcessor{},
 					Prepared:       true,
 					BuilderType:    "null",
+					SensitiveVars:  []string{},
 				},
 			},
 			false,
@@ -652,6 +663,7 @@ func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
 					PostProcessors: [][]packer.CoreBuildPostProcessor{},
 					Prepared:       true,
 					BuilderType:    "null",
+					SensitiveVars:  []string{},
 				},
 			},
 			false,
diff --git a/hcl2template/types.build_test.go b/hcl2template/types.build_test.go
index 5244712e2ea..497f78cbba2 100644
--- a/hcl2template/types.build_test.go
+++ b/hcl2template/types.build_test.go
@@ -106,7 +106,8 @@ func TestParse_build(t *testing.T) {
 			},
 			true, true,
 			[]*packer.CoreBuild{&packer.CoreBuild{
-				Provisioners: []packer.CoreBuildProvisioner{},
+				Provisioners:  []packer.CoreBuildProvisioner{},
+				SensitiveVars: []string{},
 			}},
 			false,
 			nil,
@@ -148,7 +149,9 @@ func TestParse_build(t *testing.T) {
 				Builds:                  nil,
 			},
 			true, true,
-			[]*packer.CoreBuild{&packer.CoreBuild{}},
+			[]*packer.CoreBuild{&packer.CoreBuild{
+				SensitiveVars: []string{},
+			}},
 			false,
 			nil,
 		},
@@ -190,6 +193,7 @@ func TestParse_build(t *testing.T) {
 			true, true,
 			[]*packer.CoreBuild{&packer.CoreBuild{
 				PostProcessors: [][]packer.CoreBuildPostProcessor{},
+				SensitiveVars:  []string{},
 			}},
 			true,
 			nil,
@@ -289,11 +293,12 @@ func TestParse_build(t *testing.T) {
 			false, false,
 			[]*packer.CoreBuild{
 				&packer.CoreBuild{
-					Type:         "virtualbox-iso.ubuntu-1204",
-					BuilderType:  "virtualbox-iso",
-					Prepared:     true,
-					Builder:      emptyMockBuilder,
-					Provisioners: []packer.CoreBuildProvisioner{},
+					Type:          "virtualbox-iso.ubuntu-1204",
+					BuilderType:   "virtualbox-iso",
+					Prepared:      true,
+					Builder:       emptyMockBuilder,
+					Provisioners:  []packer.CoreBuildProvisioner{},
+					SensitiveVars: []string{},
 					PostProcessors: [][]packer.CoreBuildPostProcessor{
 						{
 							{
@@ -324,11 +329,12 @@ func TestParse_build(t *testing.T) {
 					},
 				},
 				&packer.CoreBuild{
-					Type:         "amazon-ebs.aws-ubuntu-16.04",
-					BuilderType:  "amazon-ebs",
-					Prepared:     true,
-					Builder:      emptyMockBuilder,
-					Provisioners: []packer.CoreBuildProvisioner{},
+					Type:          "amazon-ebs.aws-ubuntu-16.04",
+					BuilderType:   "amazon-ebs",
+					Prepared:      true,
+					Builder:       emptyMockBuilder,
+					Provisioners:  []packer.CoreBuildProvisioner{},
+					SensitiveVars: []string{},
 					PostProcessors: [][]packer.CoreBuildPostProcessor{
 						{
 							{
@@ -407,10 +413,11 @@ func TestParse_build(t *testing.T) {
 			false, false,
 			[]*packer.CoreBuild{
 				&packer.CoreBuild{
-					Type:        "virtualbox-iso.ubuntu-1204",
-					BuilderType: "virtualbox-iso",
-					Prepared:    true,
-					Builder:     emptyMockBuilder,
+					Type:          "virtualbox-iso.ubuntu-1204",
+					BuilderType:   "virtualbox-iso",
+					Prepared:      true,
+					Builder:       emptyMockBuilder,
+					SensitiveVars: []string{},
 					Provisioners: []packer.CoreBuildProvisioner{
 						{
 							PType: "shell",
@@ -438,10 +445,11 @@ func TestParse_build(t *testing.T) {
 					PostProcessors: [][]packer.CoreBuildPostProcessor{},
 				},
 				&packer.CoreBuild{
-					Type:        "amazon-ebs.aws-ubuntu-16.04",
-					BuilderType: "amazon-ebs",
-					Prepared:    true,
-					Builder:     emptyMockBuilder,
+					Type:          "amazon-ebs.aws-ubuntu-16.04",
+					BuilderType:   "amazon-ebs",
+					Prepared:      true,
+					Builder:       emptyMockBuilder,
+					SensitiveVars: []string{},
 					Provisioners: []packer.CoreBuildProvisioner{
 						{
 							PType: "file",
@@ -499,10 +507,11 @@ func TestParse_build(t *testing.T) {
 			false, false,
 			[]*packer.CoreBuild{
 				&packer.CoreBuild{
-					Type:        "virtualbox-iso.ubuntu-1204",
-					BuilderType: "virtualbox-iso",
-					Prepared:    true,
-					Builder:     emptyMockBuilder,
+					Type:          "virtualbox-iso.ubuntu-1204",
+					BuilderType:   "virtualbox-iso",
+					Prepared:      true,
+					Builder:       emptyMockBuilder,
+					SensitiveVars: []string{},
 					Provisioners: []packer.CoreBuildProvisioner{
 						{
 							PType: "shell",
@@ -570,6 +579,7 @@ func TestParse_build(t *testing.T) {
 					Builder:        emptyMockBuilder,
 					Provisioners:   []packer.CoreBuildProvisioner{},
 					PostProcessors: [][]packer.CoreBuildPostProcessor{},
+					SensitiveVars:  []string{},
 				},
 			},
 			false,
@@ -620,12 +630,13 @@ func TestParse_build(t *testing.T) {
 			false, false,
 			[]*packer.CoreBuild{
 				&packer.CoreBuild{
-					BuildName:    "test-build",
-					Type:         "virtualbox-iso.ubuntu-1204",
-					BuilderType:  "virtualbox-iso",
-					Prepared:     true,
-					Builder:      emptyMockBuilder,
-					Provisioners: []packer.CoreBuildProvisioner{},
+					BuildName:     "test-build",
+					Type:          "virtualbox-iso.ubuntu-1204",
+					BuilderType:   "virtualbox-iso",
+					Prepared:      true,
+					Builder:       emptyMockBuilder,
+					Provisioners:  []packer.CoreBuildProvisioner{},
+					SensitiveVars: []string{},
 					PostProcessors: [][]packer.CoreBuildPostProcessor{
 						{
 							{
@@ -679,11 +690,12 @@ func TestParse_build(t *testing.T) {
 			false, false,
 			[]*packer.CoreBuild{
 				&packer.CoreBuild{
-					BuildName:   "build-name-test",
-					Type:        "virtualbox-iso.ubuntu-1204",
-					BuilderType: "virtualbox-iso",
-					Prepared:    true,
-					Builder:     emptyMockBuilder,
+					BuildName:     "build-name-test",
+					Type:          "virtualbox-iso.ubuntu-1204",
+					BuilderType:   "virtualbox-iso",
+					Prepared:      true,
+					Builder:       emptyMockBuilder,
+					SensitiveVars: []string{},
 					Provisioners: []packer.CoreBuildProvisioner{
 						{
 							PName: "build-name-test",
diff --git a/hcl2template/types.datasource_test.go b/hcl2template/types.datasource_test.go
index d0125974d7d..e066a8f3243 100644
--- a/hcl2template/types.datasource_test.go
+++ b/hcl2template/types.datasource_test.go
@@ -61,6 +61,7 @@ func TestParse_datasource(t *testing.T) {
 					Provisioners:   []packer.CoreBuildProvisioner{},
 					PostProcessors: [][]packer.CoreBuildPostProcessor{},
 					Prepared:       true,
+					SensitiveVars:  []string{},
 				},
 			},
 			false,
@@ -150,6 +151,7 @@ func TestParse_datasource(t *testing.T) {
 					Provisioners:   []packer.CoreBuildProvisioner{},
 					PostProcessors: [][]packer.CoreBuildPostProcessor{},
 					Prepared:       true,
+					SensitiveVars:  []string{},
 				},
 			},
 			false,
diff --git a/hcl2template/types.packer_config_test.go b/hcl2template/types.packer_config_test.go
index 56658120189..6d62ab0da51 100644
--- a/hcl2template/types.packer_config_test.go
+++ b/hcl2template/types.packer_config_test.go
@@ -206,9 +206,10 @@ func TestParser_complete(t *testing.T) {
 			false, false,
 			[]*packer.CoreBuild{
 				&packer.CoreBuild{
-					Type:        "virtualbox-iso.ubuntu-1204",
-					BuilderType: "virtualbox-iso",
-					Prepared:    true,
+					Type:          "virtualbox-iso.ubuntu-1204",
+					BuilderType:   "virtualbox-iso",
+					Prepared:      true,
+					SensitiveVars: []string{},
 					Builder: &MockBuilder{
 						Config: MockConfig{
 							NestedMockConfig: NestedMockConfig{
@@ -318,9 +319,10 @@ func TestParser_complete(t *testing.T) {
 					},
 				},
 				&packer.CoreBuild{
-					Type:        "amazon-ebs.ubuntu-1604",
-					BuilderType: "amazon-ebs",
-					Prepared:    true,
+					Type:          "amazon-ebs.ubuntu-1604",
+					BuilderType:   "amazon-ebs",
+					Prepared:      true,
+					SensitiveVars: []string{},
 					Builder: &MockBuilder{
 						Config: MockConfig{
 							NestedMockConfig: NestedMockConfig{
diff --git a/hcl2template/types.source_test.go b/hcl2template/types.source_test.go
index 5acf156380b..15e1d2b3ad6 100644
--- a/hcl2template/types.source_test.go
+++ b/hcl2template/types.source_test.go
@@ -59,6 +59,7 @@ func TestParse_source(t *testing.T) {
 					Provisioners:   []packer.CoreBuildProvisioner{},
 					PostProcessors: [][]packer.CoreBuildPostProcessor{},
 					Prepared:       true,
+					SensitiveVars:  []string{},
 				},
 			},
 			false,
diff --git a/hcl2template/types.variables_test.go b/hcl2template/types.variables_test.go
index 07fb8c2a517..30fb457aed6 100644
--- a/hcl2template/types.variables_test.go
+++ b/hcl2template/types.variables_test.go
@@ -133,6 +133,7 @@ func TestParse_variables(t *testing.T) {
 					Provisioners:   []packer.CoreBuildProvisioner{},
 					PostProcessors: [][]packer.CoreBuildPostProcessor{},
 					Prepared:       true,
+					SensitiveVars:  []string{"super_secret_password"},
 				},
 			},
 			false,
@@ -305,6 +306,7 @@ func TestParse_variables(t *testing.T) {
 					Provisioners:   []packer.CoreBuildProvisioner{},
 					PostProcessors: [][]packer.CoreBuildPostProcessor{},
 					Prepared:       true,
+					SensitiveVars:  []string{},
 				},
 			},
 			false,
@@ -393,6 +395,7 @@ func TestParse_variables(t *testing.T) {
 					Provisioners:   []packer.CoreBuildProvisioner{},
 					PostProcessors: [][]packer.CoreBuildPostProcessor{},
 					Prepared:       true,
+					SensitiveVars:  []string{},
 				},
 			},
 			false,
@@ -459,6 +462,7 @@ func TestParse_variables(t *testing.T) {
 					Provisioners:   []packer.CoreBuildProvisioner{},
 					PostProcessors: [][]packer.CoreBuildPostProcessor{},
 					Prepared:       true,
+					SensitiveVars:  []string{},
 				},
 			},
 			false,
@@ -502,6 +506,7 @@ func TestParse_variables(t *testing.T) {
 					Provisioners:   []packer.CoreBuildProvisioner{},
 					PostProcessors: [][]packer.CoreBuildPostProcessor{},
 					Prepared:       true,
+					SensitiveVars:  []string{},
 				},
 			},
 			false,
@@ -594,6 +599,7 @@ func TestParse_variables(t *testing.T) {
 						},
 					},
 					PostProcessors: [][]packer.CoreBuildPostProcessor{},
+					SensitiveVars:  []string{},
 				},
 			},
 			false,
@@ -651,6 +657,7 @@ func TestParse_variables(t *testing.T) {
 					Provisioners:   []packer.CoreBuildProvisioner{},
 					PostProcessors: [][]packer.CoreBuildPostProcessor{},
 					Prepared:       true,
+					SensitiveVars:  []string{},
 				},
 			},
 			false,
diff --git a/packer/build_test.go b/packer/build_test.go
index c15eec5b570..9f572101d22 100644
--- a/packer/build_test.go
+++ b/packer/build_test.go
@@ -39,8 +39,9 @@ func testBuild() *CoreBuild {
 				{&MockPostProcessor{ArtifactId: "pp"}, "testPP", "testPPName", cty.Value{}, make(map[string]interface{}), boolPointer(true)},
 			},
 		},
-		Variables: make(map[string]string),
-		onError:   "cleanup",
+		Variables:     make(map[string]string),
+		onError:       "cleanup",
+		SensitiveVars: []string{"sensitive_var"},
 	}
 }
 
@@ -54,6 +55,7 @@ func testDefaultPackerConfig() map[string]interface{} {
 		common.OnErrorConfigKey:       "cleanup",
 		common.TemplatePathKey:        "",
 		common.UserVariablesConfigKey: make(map[string]string),
+		common.SensitiveVarsConfigKey: []string{"sensitive_var"},
 	}
 }
 func TestBuild_Name(t *testing.T) {