Provisioners are not unsafe by themselves, but HashiCorp advises exhausting all alternatives first. They run commands outside Terraform's model, usually need network access and credentials to your servers, and add risk that is hard to review in a plan.
What provisioners are
A provisioner is a block inside a resource that runs an action after the resource is created. There are three built in types: file copies files to the new resource, local-exec runs an executable on the machine running Terraform, and remote-exec runs one on the remote resource.
Why the documentation warns against them
The Terraform documentation gives two reasons. Terraform cannot predictably model provisioner behavior, so a plan does not show what a script will do. And most provisioners require direct network access to your servers and credentials to install software, which the page says introduces complexity and potential security issues.
For a reviewer, that means a short local-exec command is invisible in the plan output. The security question moves from "what resources change" to "what does this script do, with which credentials, on which machine".
The SSH host key default
For SSH connections, the documentation states that host key validation is disabled by default, because SSH is most often used with newly created machines. If that is not acceptable, you can set up your own key distribution and set the host_key argument to verify a specific key or signing CA.
Risk table
| Provisioner | Runs where | Main review concern |
|---|---|---|
local-exec | Terraform runner | Shell commands with the runner's credentials, and input values that reach the command |
remote-exec | Target server | Network path, login credentials, unverified host key by default |
file | Target server | What is copied, and where the secrets come from |
Safer patterns
- Check whether the provider offers a first class way to do the task.
- Bake software into a machine image so there is nothing to run after creation.
- Use configuration management or cloud init mechanisms for post creation setup.
- If you must use a provisioner, set
host_keyand keep scripts in version control. - Use ephemeral values in provisioner and connection blocks where your Terraform version supports it (1.10 and later), so credentials are not kept in state.
What to flag in review
- Any new provisioner block, with a note on why no alternative works.
- Commands built from variables or data source output.
- Connection blocks with passwords or private keys.
on_failure = continue, which lets a failed script go unnoticed.
Try it yourself
Click through it at your own pace, or open it full screen. See how a change can be held for review, and consider adding any new provisioner block to your own review triggers.
Quick check
Is local-exec more dangerous than remote-exec?
They carry different risks. local-exec uses the runner's credentials and network position, while remote-exec uses a login to the target.
Do provisioners show up in terraform plan?
The block is part of the configuration, but the plan cannot predict what the command will do.
Is there a built in way to avoid provisioners?
Often yes: provider arguments, machine images or configuration management, depending on the task.
Safeguard offers SBOM and dependency scanning and policy gates that can block a pull request on findings, and you can try a free scan at gold.safeguard.sh/scan.
Sources
Last reviewed: 19 October 2026.