puppetlabs/puppet · error · ArgumentError

invalid key

Error message

invalid key

What it means

Before touching disk, the MessagePack terminus validates the key against Puppet::Indirector::BadNameRegexp, which matches a leading '..', any '/' or '\\', a NUL byte, or a leading Windows drive-letter prefix. A match means the key could escape the indirection's data directory (directory traversal), so Puppet logs crit 'directory traversal detected in <class>: <name>' and raises ArgumentError 'invalid key'.

Source

Thrown at lib/puppet/indirector/msgpack.rb:52

  rescue => detail
    unless detail.is_a? Errno::ENOENT
      raise Puppet::Error, _("Could not destroy %{name} %{request}: %{detail}") % { name: name, request: request.key, detail: detail }, detail.backtrace
    end

    1 # emulate success...
  end

  def search(request)
    Dir.glob(path(request.key)).collect do |file|
      load_msgpack_from_file(file, request.key)
    end
  end

  # Return the path to a given node's file.
  def path(name, ext = '.msgpack')
    if name =~ Puppet::Indirector::BadNameRegexp then
      Puppet.crit(_("directory traversal detected in %{indirection}: %{name}") % { indirection: self.class, name: name.inspect })
      raise ArgumentError, _("invalid key")
    end

    base = Puppet.run_mode.server? ? Puppet[:server_datadir] : Puppet[:client_datadir]
    File.join(base, self.class.indirection_name.to_s, name.to_s + ext)
  end

  private

  def load_msgpack_from_file(file, key)
    msgpack = nil

    begin
      msgpack = Puppet::FileSystem.read(file, :encoding => 'utf-8')
    rescue Errno::ENOENT
      return nil
    rescue => detail
      # TRANSLATORS "MessagePack" is a program name and should not be translated
      raise Puppet::Error, _("Could not read MessagePack data for %{indirection} %{key}: %{detail}") % { indirection: indirection.name, key: key, detail: detail }, detail.backtrace

View on GitHub (pinned to e227c27540)

Solutions

  1. Sanitize the key before the call: replace path separators, NULs, and leading '..' sequences.
  2. Encode special identifiers (URL-encode or digest) rather than passing them raw.
  3. Validate names at your API boundary and reject bad ones early.
  4. Change the naming scheme if provisioning produces keys with separators.

Example fix

# before
indirection.destroy('web/server01')
# crit: directory traversal detected ... ArgumentError: invalid key

# after
safe_key = 'web/server01'.tr('/', '_')
indirection.destroy(safe_key)
Defensive patterns

Strategy: validation

Validate before calling

raise ArgumentError, 'unsafe key ' + key.inspect if key.to_s.match?(Puppet::Indirector::BadNameRegexp)
safe_key = key.tr('/', '_')

Type guard

def safe_indirector_key?(name)
  name.is_a?(String) && !name.match?(Puppet::Indirector::BadNameRegexp)
end

Prevention

When it happens

Trigger: Calling find/save/destroy on a msgpack-backed indirection with a key containing a slash, a leading '..', an absolute path, a NUL byte, or a 'C:'-style Windows drive prefix.

Common situations: Certnames or identifiers containing separators fed straight from user input; code reusing file paths as keys; cross-platform names accidentally carrying a drive-letter prefix.

Related errors


AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21). Data as JSON: /api/errors/c88a39daa0630d10. Report an issue: GitHub.