Packer Sensitive Variables: Architecture Note for Secret Handling in Image Builds
Marking Packer variables as sensitive redacts values from logs and manifests but does not encrypt secrets or stop provisioners from leaking them. This architecture note covers requirements, minimal design, and failure modes.
20 Apr 2026, 03:54 UTC

Image builds often require credentials for cloud authentication, SSH access, or license keys. Without proper handling, these values routinely leak into Packer logs, manifests, and CI artifacts. Marking a variable as sensitive in Packer suppresses the value from Packer’s own standard output and artifact metadata, but it does not encrypt the secret or prevent a provisioner from printing it. Use sensitive = true as a containment boundary, not as a primary secret store.
Requirements for Sensitive Variables
Packer HCL2 templates support a variable attribute that controls redaction. To implement this, the variable must be declared in the template with the attribute set to true. Values can be supplied at build time via the CLI, environment variables, or variable files, and Packer will treat them as confidential for its own internal logging.
Minimum declaration:
variable "ssh_password" {
type = string
sensitive = true
}
CLI equivalent:
packer build -var "ssh_password=mysecret" template.pkr.hcl
Run these commands on a machine with Packer installed and read access to the template. Required permissions include template read access and execution rights for the Packer binary. Risk: Passing secrets directly on the command line exposes them to process listings (e.g., ps aux) and shell history files.
Smallest Suitable Design
The most secure minimal design involves declaring one variable block per secret and referencing that variable only inside the specific provisioners that require it. Avoid passing these variables to post-processors that write metadata files.
source "amazon-ebs" "ubuntu" {
ami_name = "example-{{timestamp}}"
}
build {
sources = ["source.amazon-ebs.ubuntu"]
provisioner "shell" {
environment_vars = [
"SSH_PASSWORD=${var.ssh_password}"
]
inline = [
"echo setting up user"
]
}
}
In this design, the variable is referenced only in the provisioner environment. Do not include it in source blocks, post-processor configurations, or output blocks to limit the surface area where Packer might serialize the value.
Trust and Data Boundaries
Packer maintains the variable value in process memory for the duration of the build. By design, Packer does not write sensitive variable values to the local cache, the manifest file, or generated artifacts unless a provisioner explicitly outputs the value. The boundary is Packer’s own logging and metadata emission, not the builder host or the provisioner runtime.
What is not protected: The plaintext secret remains in memory and is visible to any process capable of inspecting the Packer process. Furthermore, it is passed as an environment variable or command argument to provisioners. If the secret is stored in a version-controlled .pkrvars.hcl file, anyone with repository access can read it regardless of the sensitive = true flag.
Operational Checks
Verify redaction and containment before promoting a template to production.
- Inspect variable definitions: Run
packer inspect -type=variables template.pkr.hclon the build host. Expected check: The output lists the variable withsensitive = true. Note thatinspectdoes not reveal the actual value. - Build with verbose logging: Run
packer build -color=false template.pkr.hclin a test environment. Expected check: Console output shows(sensitive value)or omits the value entirely. Review CI logs for accidental echoes. - Check artifact metadata: After a build, open the generated
manifest.json. Expected check: No secret values are present. If a post-processor writes a manifest, confirm its documentation states it respects sensitive variables.
Audit all provisioner scripts for commands that print variables, such as echo $SSH_PASSWORD or debug dumps. These statements bypass Packer’s redaction mechanisms.
Failure Modes
- Provisioner Leakage: A shell or PowerShell provisioner that prints the variable writes the secret directly to the build logs. Packer cannot redact these values after they are emitted by the guest OS.
- Post-processor Export: Post-processors like
manifestor custom file writers can be configured to include variable values in output. If enabled, the sensitivity guarantee is broken and the secret is stored in the resulting JSON or artifact. - Var File Exposure: Storing plaintext secrets in
.pkrvars.hclunder version control exposes them to all repository readers.sensitive = trueonly affects Packer's output, not the source file's access controls. - Memory Inspection: Marking a variable sensitive does not encrypt it in memory. Co-located processes or core dumps can expose the value.
When to Change the Design
Transition to an external secret manager when secrets must not exist as plaintext in the build environment. Options include HashiCorp Vault, AWS Secrets Manager, or CI secret injection using short-lived tokens. In that model, Packer retrieves a secret at build time via a data source or provisioner, ensuring the secret never appears in variable files.
Consider isolated provisioner execution if provisioners run in containers or ephemeral VMs that receive secrets via runtime injection and are destroyed immediately after use. This reduces the window for memory-based leakage.
Limitations: Sensitive variables provide output redaction only. They do not provide encryption, access control, or audit logging. For higher assurance, combine redaction with external secret storage, least-privilege CI runners, and automated log scrubbing.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.