hashicorp/vagrant · error · VagrantPlugins::Salt::Errors::InvalidShasumError

The bootstrap-salt script downloaded from '%{source}' couldn

Error message

The bootstrap-salt script downloaded from '%{source}' couldn't be verified. Expected SHA256 '%{expected_sha}', but computed '%{computed_sha}'

What it means

Raised by Vagrant's salt BootstrapDownloader when verifying the salt-bootstrap script: it downloads the script from the GitHub 'latest' release URL (bootstrap-salt.sh, or .ps1 for Windows guests), downloads the matching '.sha256' sidecar, extracts the last 64-char hex token via regex, computes SHA256 of the script, and raises InvalidShasumError with source/expected/computed on mismatch. Because the URL pins to 'latest' rather than a fixed release, any upstream republish, CDN skew between the script and its sidecar, or corrupted/proxied download makes verification fail.

Source

Thrown at plugins/provisioners/salt/bootstrap_downloader.rb:48

        @logger.info "Downloaded and verified salt-bootstrap script"
        script_file
      end

      def verify_sha256(script)
        @logger.debug "Downloading sha256 file from #{source_url}#{SHA256_SUFFIX}"
        sha256_file = download("#{source_url}#{SHA256_SUFFIX}")
        sha256 = extract_sha256(sha256_file.read)
        sha256_file.close

        @logger.debug "Computing sha256 value from script file"
        computed_sha256 = Digest::SHA256.hexdigest(script.read)
        script.rewind

        @logger.debug "Comparing sha256 values"
        if computed_sha256 != sha256
          @logger.debug "Mismatched sha256, expected #{sha256} but computed #{computed_sha256}"
          raise Salt::Errors::InvalidShasumError, source: source_url, expected_sha: sha256, computed_sha: computed_sha256
        end
        @logger.debug "Sha256 values match"
      end

      def extract_sha256(text)
        text.scan(/\b([a-f0-9]{64})\b/).last.first
      end

      def download(url)
        URI(url).open
      end
    end
  end
end

View on GitHub (pinned to 35f3160f4a)

Solutions

  1. Retry after a few minutes - the 'latest' release artifacts usually re-sync upstream
  2. Bypass caches: pull once on the host, verify `sha256sum bootstrap-salt.sh` against the sidecar manually, then set `salt.bootstrap_script_path` (or bootstrap_source) to that pinned local copy
  3. If behind a proxy, clear/refresh its cache for github.com/saltstack/salt-bootstrap or add an exception
  4. Report the mismatch to saltstack/salt-bootstrap if it persists - the release artifacts themselves are inconsistent

Example fix

# before (default: always chases 'latest', races .sha256 sidecar)
config.vm.provision "salt" do |s|
  s.install_master = true
end

# after (pin a local, pre-verified script)
# curl -LO https://github.com/saltstack/salt-bootstrap/releases/download/v2024.03.1/bootstrap-salt.sh
# curl -LO .../bootstrap-salt.sh.sha256 && sha256sum -c bootstrap-salt.sh.sha256
config.vm.provision "salt" do |s|
  s.install_master = true
  s.bootstrap_script_path = "vendor/bootstrap-salt.sh"
end
Defensive patterns

Strategy: validation

Validate before calling

# Pin and verify the bootstrap script on the host before provisioning
require "digest"
require "open-uri"
script = URI.open("https://github.com/saltstack/salt-bootstrap/releases/download/v2024.03.1/bootstrap-salt.sh")
expected = URI.open("https://github.com/saltstack/salt-bootstrap/releases/download/v2024.03.1/bootstrap-salt.sh.sha256").read[/\b([a-f0-9]{64})\b/]
abort "sha mismatch" unless Digest::SHA256.hexdigest(script.read) == expected
File.binwrite("vendor/bootstrap-salt.sh", script.rewind && script.read)

config.vm.provision "salt" do |s|
  s.bootstrap_script_path = "vendor/bootstrap-salt.sh"
end

Type guard

def bootstrap_script_verified?(path, sha256_file)
  expected = File.read(sha256_file)[/\b([a-f0-9]{64})\b/]
  Digest::SHA256.hexdigest(File.read(path)) == expected
end

Try / catch

begin
  env.cli(%w[provision])
rescue VagrantPlugins::Salt::Errors::InvalidShasumError => e
  # 'latest' release artifacts raced - clear caches and retry once
  sleep 120
  retry
end

Prevention

When it happens

Trigger: Provisioning with the salt provisioner (default bootstrap_source) when the downloaded bootstrap-salt.sh digest does not equal the digest in bootstrap-salt.sh.sha256 - typically a race between artifact uploads on a fresh 'latest' release, a caching proxy serving mixed versions, or a truncated download.

Common situations: salt-bootstrap cutting a release minutes before you provision (script and .sha256 briefly inconsistent); corporate proxy/CDN caching one file from the old release and one from the new; MITM or AV stripping/modifying the shell script; Windows guests hitting the .ps1 variant of the same race.

Related errors


AI-assisted analysis of hashicorp/vagrant@35f3160f4a (2026-08-21). Data as JSON: /api/errors/ec53abfd74679ec1. Report an issue: GitHub.